]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmiEntry.asm
SourceLevelDebugPkg: Remove X86 ASM and S files
[mirror_edk2.git] / UefiCpuPkg / Library / SmmCpuFeaturesLib / X64 / SmiEntry.asm
CommitLineData
09119a00
MK
1;------------------------------------------------------------------------------ ;\r
2; Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
3; This program and the accompanying materials\r
4; are licensed and made available under the terms and conditions of the BSD License\r
5; which accompanies this distribution. The full text of the license may be found at\r
6; http://opensource.org/licenses/bsd-license.php.\r
7;\r
8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10;\r
11; Module Name:\r
12;\r
13; SmiEntry.asm\r
14;\r
15; Abstract:\r
16;\r
17; Code template of the SMI handler for a particular processor\r
18;\r
19;-------------------------------------------------------------------------------\r
20\r
21;\r
22; Variables referenced by C code\r
23;\r
24EXTERNDEF SmiRendezvous:PROC\r
25EXTERNDEF CpuSmmDebugEntry:PROC\r
26EXTERNDEF CpuSmmDebugExit:PROC\r
27EXTERNDEF gcStmSmiHandlerTemplate:BYTE\r
28EXTERNDEF gcStmSmiHandlerSize:WORD\r
29EXTERNDEF gcStmSmiHandlerOffset:WORD\r
30EXTERNDEF gStmSmiCr3:DWORD\r
31EXTERNDEF gStmSmiStack:DWORD\r
32EXTERNDEF gStmSmbase:DWORD\r
33EXTERNDEF gStmXdSupported:BYTE\r
34EXTERNDEF gStmSmiHandlerIdtr:FWORD\r
35\r
36MSR_IA32_MISC_ENABLE EQU 1A0h\r
37MSR_EFER EQU 0c0000080h\r
38MSR_EFER_XD EQU 0800h\r
39\r
40;\r
41; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR\r
42;\r
43DSC_OFFSET EQU 0fb00h\r
44DSC_GDTPTR EQU 48h\r
45DSC_GDTSIZ EQU 50h\r
46DSC_CS EQU 14h\r
47DSC_DS EQU 16h\r
48DSC_SS EQU 18h\r
49DSC_OTHERSEG EQU 1ah\r
50;\r
51; Constants relating to CPU State Save Area\r
52;\r
53SSM_DR6 EQU 0ffd0h\r
54SSM_DR7 EQU 0ffc8h\r
55\r
56PROTECT_MODE_CS EQU 08h\r
57PROTECT_MODE_DS EQU 20h\r
58LONG_MODE_CS EQU 38h\r
59TSS_SEGMENT EQU 40h\r
60GDT_SIZE EQU 50h\r
61\r
62 .code\r
63\r
64gcStmSmiHandlerTemplate LABEL BYTE\r
65\r
66_StmSmiEntryPoint:\r
67 ;\r
68 ; The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-\r
69 ; bit addressing mode. And that coincidence has been used in the following\r
70 ; "64-bit like" 16-bit code. Be aware that once RDI is referenced as a\r
71 ; base address register, it is actually BX that is referenced.\r
72 ;\r
73 DB 0bbh ; mov bx, imm16\r
74 DW offset _StmGdtDesc - _StmSmiEntryPoint + 8000h ; bx = GdtDesc offset\r
75; fix GDT descriptor\r
76 DB 2eh, 0a1h ; mov ax, cs:[offset16]\r
77 DW DSC_OFFSET + DSC_GDTSIZ\r
78 DB 48h ; dec ax\r
79 DB 2eh\r
80 mov [rdi], eax ; mov cs:[bx], ax\r
81 DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]\r
82 DW DSC_OFFSET + DSC_GDTPTR\r
83 DB 2eh\r
84 mov [rdi + 2], ax ; mov cs:[bx + 2], eax\r
85 DB 66h, 2eh\r
86 lgdt fword ptr [rdi] ; lgdt fword ptr cs:[bx]\r
87; Patch ProtectedMode Segment\r
88 DB 0b8h ; mov ax, imm16\r
89 DW PROTECT_MODE_CS ; set AX for segment directly\r
90 DB 2eh\r
91 mov [rdi - 2], eax ; mov cs:[bx - 2], ax\r
92; Patch ProtectedMode entry\r
93 DB 66h, 0bfh ; mov edi, SMBASE\r
94gStmSmbase DD ?\r
95 lea ax, [edi + (@ProtectedMode - _StmSmiEntryPoint) + 8000h]\r
96 DB 2eh\r
97 mov [rdi - 6], ax ; mov cs:[bx - 6], eax\r
98; Switch into @ProtectedMode\r
99 mov rbx, cr0\r
100 DB 66h\r
101 and ebx, 9ffafff3h\r
102 DB 66h\r
103 or ebx, 00000023h\r
104\r
105 mov cr0, rbx\r
106 DB 66h, 0eah\r
107 DD ?\r
108 DW ?\r
109\r
110_StmGdtDesc FWORD ?\r
111@ProtectedMode:\r
112 mov ax, PROTECT_MODE_DS\r
113 mov ds, ax\r
114 mov es, ax\r
115 mov fs, ax\r
116 mov gs, ax\r
117 mov ss, ax\r
118 DB 0bch ; mov esp, imm32\r
119gStmSmiStack DD ?\r
120 jmp ProtFlatMode\r
121\r
122ProtFlatMode:\r
123 DB 0b8h ; mov eax, offset gStmSmiCr3\r
124gStmSmiCr3 DD ?\r
125 mov cr3, rax\r
126 mov eax, 668h ; as cr4.PGE is not set here, refresh cr3\r
127 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.\r
128; Load TSS\r
129 sub esp, 8 ; reserve room in stack\r
130 sgdt fword ptr [rsp]\r
131 mov eax, [rsp + 2] ; eax = GDT base\r
132 add esp, 8\r
133 mov dl, 89h\r
134 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag\r
135 mov eax, TSS_SEGMENT\r
136 ltr ax\r
137\r
138; enable NXE if supported\r
139 DB 0b0h ; mov al, imm8\r
140gStmXdSupported DB 1\r
141 cmp al, 0\r
142 jz @SkipXd\r
143;\r
144; Check XD disable bit\r
145;\r
146 mov ecx, MSR_IA32_MISC_ENABLE\r
147 rdmsr\r
148 sub esp, 4\r
149 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]\r
150 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]\r
151 jz @f\r
152 and dx, 0FFFBh ; clear XD Disable bit if it is set\r
153 wrmsr\r
154@@:\r
155 mov ecx, MSR_EFER\r
156 rdmsr\r
157 or ax, MSR_EFER_XD ; enable NXE\r
158 wrmsr\r
159 jmp @XdDone\r
160@SkipXd:\r
161 sub esp, 8\r
162@XdDone:\r
163\r
164; Switch into @LongMode\r
165 push LONG_MODE_CS ; push cs hardcore here\r
166 call Base ; push return address for retf later\r
167Base:\r
168 add dword ptr [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg\r
169\r
170 mov ecx, MSR_EFER\r
171 rdmsr\r
172 or ah, 1 ; enable LME\r
173 wrmsr\r
174 mov rbx, cr0\r
175 or ebx, 080010023h ; enable paging + WP + NE + MP + PE\r
176 mov cr0, rbx\r
177 retf\r
178@LongMode: ; long mode (64-bit code) starts here\r
179 mov rax, offset gStmSmiHandlerIdtr\r
180 lidt fword ptr [rax]\r
181 lea ebx, [rdi + DSC_OFFSET]\r
182 mov ax, [rbx + DSC_DS]\r
183 mov ds, eax\r
184 mov ax, [rbx + DSC_OTHERSEG]\r
185 mov es, eax\r
186 mov fs, eax\r
187 mov gs, eax\r
188 mov ax, [rbx + DSC_SS]\r
189 mov ss, eax\r
190\r
191CommonHandler:\r
192 mov rbx, [rsp + 0x08] ; rbx <- CpuIndex\r
193\r
194 ;\r
195 ; Save FP registers\r
196 ;\r
197 sub rsp, 200h\r
198 DB 48h ; FXSAVE64\r
199 fxsave [rsp]\r
200\r
201 add rsp, -20h\r
202\r
203 mov rcx, rbx\r
204 mov rax, CpuSmmDebugEntry\r
205 call rax\r
206\r
207 mov rcx, rbx\r
208 mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous\r
209 call rax\r
210\r
211 mov rcx, rbx\r
212 mov rax, CpuSmmDebugExit\r
213 call rax\r
214\r
215 add rsp, 20h\r
216\r
217 ;\r
218 ; Restore FP registers\r
219 ;\r
220 DB 48h ; FXRSTOR64\r
221 fxrstor [rsp]\r
222\r
223 add rsp, 200h\r
224\r
225 mov rax, offset ASM_PFX(gStmXdSupported)\r
226 mov al, [rax]\r
227 cmp al, 0\r
228 jz @f\r
229 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]\r
230 test edx, BIT2\r
231 jz @f\r
232 mov ecx, MSR_IA32_MISC_ENABLE\r
233 rdmsr\r
234 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM\r
235 wrmsr\r
236\r
237@@:\r
238 rsm\r
239\r
240_StmSmiHandler:\r
241;\r
242; Check XD disable bit\r
243;\r
244 xor r8, r8\r
245 mov rax, offset ASM_PFX(gStmXdSupported)\r
246 mov al, [rax]\r
247 cmp al, 0\r
248 jz @StmXdDone\r
249 mov ecx, MSR_IA32_MISC_ENABLE\r
250 rdmsr\r
251 mov r8, rdx ; save MSR_IA32_MISC_ENABLE[63-32]\r
252 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]\r
253 jz @f\r
254 and dx, 0FFFBh ; clear XD Disable bit if it is set\r
255 wrmsr\r
256@@:\r
257 mov ecx, MSR_EFER\r
258 rdmsr\r
259 or ax, MSR_EFER_XD ; enable NXE\r
260 wrmsr\r
261@StmXdDone:\r
262 push r8\r
263\r
264 ; below step is needed, because STM does not run above code.\r
265 ; we have to run below code to set IDT/CR0/CR4\r
266 mov rax, offset gStmSmiHandlerIdtr\r
267 lidt fword ptr [rax]\r
268\r
269 mov rax, cr0\r
270 or eax, 80010023h ; enable paging + WP + NE + MP + PE\r
271 mov cr0, rax\r
272 mov rax, cr4\r
273 mov eax, 668h ; as cr4.PGE is not set here, refresh cr3\r
274 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.\r
275 ; STM init finish\r
276 jmp CommonHandler\r
277\r
278gcStmSmiHandlerSize DW $ - _StmSmiEntryPoint\r
279gcStmSmiHandlerOffset DW _StmSmiHandler - _StmSmiEntryPoint\r
280\r
281 END\r