]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S
UefiCpuPkg/SmmCpuFeaturesLibStm: Add STM library instance
[mirror_edk2.git] / UefiCpuPkg / Library / SmmCpuFeaturesLib / Ia32 / SmiEntry.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials
5 # are licensed and made available under the terms and conditions of the BSD License
6 # which accompanies this distribution. The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
8 #
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #
12 # Module Name:
13 #
14 # SmiEntry.S
15 #
16 # Abstract:
17 #
18 # Code template of the SMI handler for a particular processor
19 #
20 #------------------------------------------------------------------------------
21
22 ASM_GLOBAL ASM_PFX(gcStmSmiHandlerTemplate)
23 ASM_GLOBAL ASM_PFX(gcStmSmiHandlerSize)
24 ASM_GLOBAL ASM_PFX(gcStmSmiHandlerOffset)
25 ASM_GLOBAL ASM_PFX(gStmSmiCr3)
26 ASM_GLOBAL ASM_PFX(gStmSmiStack)
27 ASM_GLOBAL ASM_PFX(gStmSmbase)
28 ASM_GLOBAL ASM_PFX(gStmXdSupported)
29 ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
30 ASM_GLOBAL ASM_PFX(gStmSmiHandlerIdtr)
31
32 .equ MSR_IA32_MISC_ENABLE, 0x1A0
33 .equ MSR_EFER, 0xc0000080
34 .equ MSR_EFER_XD, 0x800
35
36 #
37 # Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
38 #
39 .equ DSC_OFFSET, 0xfb00
40 .equ DSC_GDTPTR, 0x48
41 .equ DSC_GDTSIZ, 0x50
42 .equ DSC_CS, 0x14
43 .equ DSC_DS, 0x16
44 .equ DSC_SS, 0x18
45 .equ DSC_OTHERSEG, 0x1A
46
47 .equ PROTECT_MODE_CS, 0x08
48 .equ PROTECT_MODE_DS, 0x20
49 .equ TSS_SEGMENT, 0x40
50
51 .text
52 ASM_PFX(gcStmSmiHandlerTemplate):
53
54 _StmSmiEntryPoint:
55 .byte 0xbb # mov bx, imm16
56 .word _StmGdtDesc - _StmSmiEntryPoint + 0x8000
57 .byte 0x2e,0xa1 # mov ax, cs:[offset16]
58 .word DSC_OFFSET + DSC_GDTSIZ
59 decl %eax
60 movl %eax, %cs:(%edi) # mov cs:[bx], ax
61 .byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
62 .word DSC_OFFSET + DSC_GDTPTR
63 movw %ax, %cs:2(%edi)
64 movw %ax, %bp # ebp = GDT base
65 .byte 0x66
66 lgdt %cs:(%edi)
67 # Patch ProtectedMode Segment
68 .byte 0xb8 # mov ax, imm16
69 .word PROTECT_MODE_CS # set AX for segment directly
70 movl %eax, %cs:-2(%edi) # mov cs:[bx - 2], ax
71 # Patch ProtectedMode entry
72 .byte 0x66, 0xbf # mov edi, SMBASE
73 ASM_PFX(gStmSmbase): .space 4
74 .byte 0x67
75 lea ((Start32bit - _StmSmiEntryPoint) + 0x8000)(%edi), %ax
76 movw %ax, %cs:-6(%edi)
77 movl %cr0, %ebx
78 .byte 0x66
79 andl $0x9ffafff3, %ebx
80 .byte 0x66
81 orl $0x23, %ebx
82 movl %ebx, %cr0
83 .byte 0x66,0xea
84 .space 4
85 .space 2
86 _StmGdtDesc: .space 4
87 .space 2
88
89 Start32bit:
90 movw $PROTECT_MODE_DS, %ax
91 movl %eax,%ds
92 movl %eax,%es
93 movl %eax,%fs
94 movl %eax,%gs
95 movl %eax,%ss
96 .byte 0xbc # mov esp, imm32
97 ASM_PFX(gStmSmiStack): .space 4
98 movl $ASM_PFX(gStmSmiHandlerIdtr), %eax
99 lidt (%eax)
100 jmp ProtFlatMode
101
102 ProtFlatMode:
103 .byte 0xb8 # mov eax, imm32
104 ASM_PFX(gStmSmiCr3): .space 4
105 movl %eax, %cr3
106 #
107 # Need to test for CR4 specific bit support
108 #
109 movl $1, %eax
110 cpuid # use CPUID to determine if specific CR4 bits are supported
111 xorl %eax, %eax # Clear EAX
112 testl $BIT2, %edx # Check for DE capabilities
113 jz L8
114 orl $BIT3, %eax
115 L8:
116 testl $BIT6, %edx # Check for PAE capabilities
117 jz L9
118 orl $BIT5, %eax
119 L9:
120 testl $BIT7, %edx # Check for MCE capabilities
121 jz L10
122 orl $BIT6, %eax
123 L10:
124 testl $BIT24, %edx # Check for FXSR capabilities
125 jz L11
126 orl $BIT9, %eax
127 L11:
128 testl $BIT25, %edx # Check for SSE capabilities
129 jz L12
130 orl $BIT10, %eax
131 L12: # as cr4.PGE is not set here, refresh cr3
132 movl %eax, %cr4 # in PreModifyMtrrs() to flush TLB.
133
134 cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
135 jz L5
136 # Load TSS
137 movb $0x89, (TSS_SEGMENT + 5)(%ebp) # clear busy flag
138 movl $TSS_SEGMENT, %eax
139 ltrw %ax
140 L5:
141
142 # enable NXE if supported
143 .byte 0xb0 # mov al, imm8
144 ASM_PFX(gStmXdSupported): .byte 1
145 cmpb $0, %al
146 jz SkipXd
147 #
148 # Check XD disable bit
149 #
150 movl $MSR_IA32_MISC_ENABLE, %ecx
151 rdmsr
152 pushl %edx # save MSR_IA32_MISC_ENABLE[63-32]
153 testl $BIT2, %edx # MSR_IA32_MISC_ENABLE[34]
154 jz L13
155 andw $0x0FFFB, %dx # clear XD Disable bit if it is set
156 wrmsr
157 L13:
158 movl $MSR_EFER, %ecx
159 rdmsr
160 orw $MSR_EFER_XD,%ax # enable NXE
161 wrmsr
162 jmp XdDone
163 SkipXd:
164 subl $4, %esp
165 XdDone:
166
167 movl %cr0, %ebx
168 orl $0x080010023, %ebx # enable paging + WP + NE + MP + PE
169 movl %ebx, %cr0
170 leal DSC_OFFSET(%edi),%ebx
171 movw DSC_DS(%ebx),%ax
172 movl %eax, %ds
173 movw DSC_OTHERSEG(%ebx),%ax
174 movl %eax, %es
175 movl %eax, %fs
176 movl %eax, %gs
177 movw DSC_SS(%ebx),%ax
178 movl %eax, %ss
179
180 CommonHandler:
181 movl 4(%esp), %ebx
182
183 pushl %ebx
184 movl $ASM_PFX(CpuSmmDebugEntry), %eax
185 call *%eax
186 addl $4, %esp
187
188 pushl %ebx
189 movl $ASM_PFX(SmiRendezvous), %eax
190 call *%eax
191 addl $4, %esp
192
193 pushl %ebx
194 movl $ASM_PFX(CpuSmmDebugExit), %eax
195 call *%eax
196 addl $4, %esp
197
198 movl $ASM_PFX(gStmXdSupported), %eax
199 movb (%eax), %al
200 cmpb $0, %al
201 jz L16
202 popl %edx # get saved MSR_IA32_MISC_ENABLE[63-32]
203 testl $BIT2, %edx
204 jz L16
205 movl $MSR_IA32_MISC_ENABLE, %ecx
206 rdmsr
207 orw $BIT2, %dx # set XD Disable bit if it was set before entering into SMM
208 wrmsr
209
210 L16:
211 rsm
212
213 _StmSmiHandler:
214 #
215 # Check XD disable bit
216 #
217 xorl %esi, %esi
218 movl $ASM_PFX(gStmXdSupported), %eax
219 movb (%eax), %al
220 cmpb $0, %al
221 jz StmXdDone
222 movl $MSR_IA32_MISC_ENABLE, %ecx
223 rdmsr
224 movl %edx, %esi # save MSR_IA32_MISC_ENABLE[63-32]
225 testl $BIT2, %edx # MSR_IA32_MISC_ENABLE[34]
226 jz L14
227 andw $0x0FFFB, %dx # clear XD Disable bit if it is set
228 wrmsr
229 L14:
230 movl $MSR_EFER, %ecx
231 rdmsr
232 orw $MSR_EFER_XD,%ax # enable NXE
233 wrmsr
234 StmXdDone:
235 push %esi
236
237 # below step is needed, because STM does not run above code.
238 # we have to run below code to set IDT/CR0/CR4
239 movl $ASM_PFX(gStmSmiHandlerIdtr), %eax
240 lidt (%eax)
241
242 movl %cr0, %eax
243 orl $0x80010023, %eax # enable paging + WP + NE + MP + PE
244 movl %eax, %cr0
245 #
246 # Need to test for CR4 specific bit support
247 #
248 movl $1, %eax
249 cpuid # use CPUID to determine if specific CR4 bits are supported
250 movl %cr4, %eax # init EAX
251 testl $BIT2, %edx # Check for DE capabilities
252 jz L28
253 orl $BIT3, %eax
254 L28:
255 testl $BIT6, %edx # Check for PAE capabilities
256 jz L29
257 orl $BIT5, %eax
258 L29:
259 testl $BIT7, %edx # Check for MCE capabilities
260 jz L30
261 orl $BIT6, %eax
262 L30:
263 testl $BIT24, %edx # Check for FXSR capabilities
264 jz L31
265 orl $BIT9, %eax
266 L31:
267 testl $BIT25, %edx # Check for SSE capabilities
268 jz L32
269 orl $BIT10, %eax
270 L32: # as cr4.PGE is not set here, refresh cr3
271 movl %eax, %cr4 # in PreModifyMtrrs() to flush TLB.
272 # STM init finish
273 jmp CommonHandler
274
275
276 ASM_PFX(gcStmSmiHandlerSize) : .word . - _StmSmiEntryPoint
277 ASM_PFX(gcStmSmiHandlerOffset): .word _StmSmiHandler - _StmSmiEntryPoint
278