UefiCpuPkg/PiSmmCpuDxeSmm: Refine code to avoid duplicated code.
[mirror_edk2.git] / UefiCpuPkg / Library / SmmCpuFeaturesLib / Ia32 / 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%define MSR_IA32_MISC_ENABLE 0x1A0\r
22%define MSR_EFER 0xc0000080\r
23%define MSR_EFER_XD 0x800\r
24\r
25;\r
26; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR\r
27;\r
28%define DSC_OFFSET 0xfb00\r
29%define DSC_GDTPTR 0x48\r
30%define DSC_GDTSIZ 0x50\r
31%define DSC_CS 0x14\r
32%define DSC_DS 0x16\r
33%define DSC_SS 0x18\r
34%define DSC_OTHERSEG 0x1a\r
35\r
36%define PROTECT_MODE_CS 0x8\r
37%define PROTECT_MODE_DS 0x20\r
38%define TSS_SEGMENT 0x40\r
39\r
40extern ASM_PFX(SmiRendezvous)\r
41extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))\r
42extern ASM_PFX(CpuSmmDebugEntry)\r
43extern ASM_PFX(CpuSmmDebugExit)\r
44\r
45global ASM_PFX(gcStmSmiHandlerTemplate)\r
46global ASM_PFX(gcStmSmiHandlerSize)\r
47global ASM_PFX(gcStmSmiHandlerOffset)\r
48global ASM_PFX(gStmSmiCr3)\r
49global ASM_PFX(gStmSmiStack)\r
50global ASM_PFX(gStmSmbase)\r
51global ASM_PFX(gStmXdSupported)\r
52extern ASM_PFX(gStmSmiHandlerIdtr)\r
53\r
54 SECTION .text\r
55\r
56BITS 16\r
57ASM_PFX(gcStmSmiHandlerTemplate):\r
58_StmSmiEntryPoint:\r
59 mov bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000\r
60 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]\r
61 dec ax\r
62 mov [cs:bx], ax\r
63 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]\r
64 mov [cs:bx + 2], eax\r
65 mov ebp, eax ; ebp = GDT base\r
66o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]\r
67 mov ax, PROTECT_MODE_CS\r
68 mov [cs:bx-0x2],ax\r
69 DB 0x66, 0xbf ; mov edi, SMBASE\r
70ASM_PFX(gStmSmbase): DD 0\r
71 lea eax, [edi + (@32bit - _StmSmiEntryPoint) + 0x8000]\r
72 mov [cs:bx-0x6],eax\r
73 mov ebx, cr0\r
74 and ebx, 0x9ffafff3\r
75 or ebx, 0x23\r
76 mov cr0, ebx\r
77 jmp dword 0x0:0x0\r
78_StmGdtDesc:\r
79 DW 0\r
80 DD 0\r
81\r
82BITS 32\r
83@32bit:\r
84 mov ax, PROTECT_MODE_DS\r
85o16 mov ds, ax\r
86o16 mov es, ax\r
87o16 mov fs, ax\r
88o16 mov gs, ax\r
89o16 mov ss, ax\r
90 DB 0xbc ; mov esp, imm32\r
91ASM_PFX(gStmSmiStack): DD 0\r
92 mov eax, ASM_PFX(gStmSmiHandlerIdtr)\r
93 lidt [eax]\r
94 jmp ProtFlatMode\r
95\r
96ProtFlatMode:\r
97 DB 0xb8 ; mov eax, imm32\r
98ASM_PFX(gStmSmiCr3): DD 0\r
99 mov cr3, eax\r
100;\r
101; Need to test for CR4 specific bit support\r
102;\r
103 mov eax, 1\r
104 cpuid ; use CPUID to determine if specific CR4 bits are supported\r
105 xor eax, eax ; Clear EAX\r
106 test edx, BIT2 ; Check for DE capabilities\r
107 jz .0\r
108 or eax, BIT3\r
109.0:\r
110 test edx, BIT6 ; Check for PAE capabilities\r
111 jz .1\r
112 or eax, BIT5\r
113.1:\r
114 test edx, BIT7 ; Check for MCE capabilities\r
115 jz .2\r
116 or eax, BIT6\r
117.2:\r
118 test edx, BIT24 ; Check for FXSR capabilities\r
119 jz .3\r
120 or eax, BIT9\r
121.3:\r
122 test edx, BIT25 ; Check for SSE capabilities\r
123 jz .4\r
124 or eax, BIT10\r
125.4: ; as cr4.PGE is not set here, refresh cr3\r
126 mov cr4, eax ; in PreModifyMtrrs() to flush TLB.\r
127\r
128 cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0\r
129 jz .6\r
130; Load TSS\r
131 mov byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag\r
132 mov eax, TSS_SEGMENT\r
133 ltr ax\r
134.6:\r
135\r
136; enable NXE if supported\r
137 DB 0b0h ; mov al, imm8\r
138ASM_PFX(gStmXdSupported): DB 1\r
139 cmp al, 0\r
140 jz @SkipXd\r
141;\r
142; Check XD disable bit\r
143;\r
144 mov ecx, MSR_IA32_MISC_ENABLE\r
145 rdmsr\r
146 push edx ; save MSR_IA32_MISC_ENABLE[63-32]\r
147 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]\r
148 jz .5\r
149 and dx, 0xFFFB ; clear XD Disable bit if it is set\r
150 wrmsr\r
151.5:\r
152 mov ecx, MSR_EFER\r
153 rdmsr\r
154 or ax, MSR_EFER_XD ; enable NXE\r
155 wrmsr\r
156 jmp @XdDone\r
157@SkipXd:\r
158 sub esp, 4\r
159@XdDone:\r
160\r
161 mov ebx, cr0\r
162 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE\r
163 mov cr0, ebx\r
164 lea ebx, [edi + DSC_OFFSET]\r
165 mov ax, [ebx + DSC_DS]\r
166 mov ds, eax\r
167 mov ax, [ebx + DSC_OTHERSEG]\r
168 mov es, eax\r
169 mov fs, eax\r
170 mov gs, eax\r
171 mov ax, [ebx + DSC_SS]\r
172 mov ss, eax\r
173\r
174CommonHandler:\r
175 mov ebx, [esp + 4] ; CPU Index\r
176 push ebx\r
177 mov eax, ASM_PFX(CpuSmmDebugEntry)\r
178 call eax\r
179 add esp, 4\r
180\r
181 push ebx\r
182 mov eax, ASM_PFX(SmiRendezvous)\r
183 call eax\r
184 add esp, 4\r
185\r
186 push ebx\r
187 mov eax, ASM_PFX(CpuSmmDebugExit)\r
188 call eax\r
189 add esp, 4\r
190\r
191 mov eax, ASM_PFX(gStmXdSupported)\r
192 mov al, [eax]\r
193 cmp al, 0\r
194 jz .7\r
195 pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]\r
196 test edx, BIT2\r
197 jz .7\r
198 mov ecx, MSR_IA32_MISC_ENABLE\r
199 rdmsr\r
200 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM\r
201 wrmsr\r
202\r
203.7:\r
204 rsm\r
205\r
206\r
207_StmSmiHandler:\r
208;\r
209; Check XD disable bit\r
210;\r
211 xor esi, esi\r
212 mov eax, ASM_PFX(gStmXdSupported)\r
213 mov al, [eax]\r
214 cmp al, 0\r
215 jz @StmXdDone\r
216 mov ecx, MSR_IA32_MISC_ENABLE\r
217 rdmsr\r
218 mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32]\r
219 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]\r
220 jz .5\r
221 and dx, 0xFFFB ; clear XD Disable bit if it is set\r
222 wrmsr\r
223.5:\r
224 mov ecx, MSR_EFER\r
225 rdmsr\r
226 or ax, MSR_EFER_XD ; enable NXE\r
227 wrmsr\r
228@StmXdDone:\r
229 push esi\r
230\r
231 ; below step is needed, because STM does not run above code.\r
232 ; we have to run below code to set IDT/CR0/CR4\r
233 mov eax, ASM_PFX(gStmSmiHandlerIdtr)\r
234 lidt [eax]\r
235\r
236 mov eax, cr0\r
237 or eax, 0x80010023 ; enable paging + WP + NE + MP + PE\r
238 mov cr0, eax\r
239;\r
240; Need to test for CR4 specific bit support\r
241;\r
242 mov eax, 1\r
243 cpuid ; use CPUID to determine if specific CR4 bits are supported\r
244 mov eax, cr4 ; init EAX\r
245 test edx, BIT2 ; Check for DE capabilities\r
246 jz .0\r
247 or eax, BIT3\r
248.0:\r
249 test edx, BIT6 ; Check for PAE capabilities\r
250 jz .1\r
251 or eax, BIT5\r
252.1:\r
253 test edx, BIT7 ; Check for MCE capabilities\r
254 jz .2\r
255 or eax, BIT6\r
256.2:\r
257 test edx, BIT24 ; Check for FXSR capabilities\r
258 jz .3\r
259 or eax, BIT9\r
260.3:\r
261 test edx, BIT25 ; Check for SSE capabilities\r
262 jz .4\r
263 or eax, BIT10\r
264.4: ; as cr4.PGE is not set here, refresh cr3\r
265 mov cr4, eax ; in PreModifyMtrrs() to flush TLB.\r
266 ; STM init finish\r
267 jmp CommonHandler\r
268\r
269ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint\r
270ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint\r
271\r