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