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