]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiException.asm
Correct TSS segment.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiException.asm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2009 - 2015, 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 ; SmiException.asm
14 ;
15 ; Abstract:
16 ;
17 ; Exception handlers used in SM mode
18 ;
19 ;-------------------------------------------------------------------------------
20
21 EXTERNDEF SmiPFHandler:PROC
22 EXTERNDEF gSmiMtrrs:QWORD
23 EXTERNDEF gcSmiIdtr:FWORD
24 EXTERNDEF gcSmiGdtr:FWORD
25 EXTERNDEF gcPsd:BYTE
26
27 .const
28
29 NullSeg DQ 0 ; reserved by architecture
30 CodeSeg32 LABEL QWORD
31 DW -1 ; LimitLow
32 DW 0 ; BaseLow
33 DB 0 ; BaseMid
34 DB 9bh
35 DB 0cfh ; LimitHigh
36 DB 0 ; BaseHigh
37 ProtModeCodeSeg32 LABEL QWORD
38 DW -1 ; LimitLow
39 DW 0 ; BaseLow
40 DB 0 ; BaseMid
41 DB 9bh
42 DB 0cfh ; LimitHigh
43 DB 0 ; BaseHigh
44 ProtModeSsSeg32 LABEL QWORD
45 DW -1 ; LimitLow
46 DW 0 ; BaseLow
47 DB 0 ; BaseMid
48 DB 93h
49 DB 0cfh ; LimitHigh
50 DB 0 ; BaseHigh
51 DataSeg32 LABEL QWORD
52 DW -1 ; LimitLow
53 DW 0 ; BaseLow
54 DB 0 ; BaseMid
55 DB 93h
56 DB 0cfh ; LimitHigh
57 DB 0 ; BaseHigh
58 CodeSeg16 LABEL QWORD
59 DW -1
60 DW 0
61 DB 0
62 DB 9bh
63 DB 8fh
64 DB 0
65 DataSeg16 LABEL QWORD
66 DW -1
67 DW 0
68 DB 0
69 DB 93h
70 DB 8fh
71 DB 0
72 CodeSeg64 LABEL QWORD
73 DW -1 ; LimitLow
74 DW 0 ; BaseLow
75 DB 0 ; BaseMid
76 DB 9bh
77 DB 0afh ; LimitHigh
78 DB 0 ; BaseHigh
79 ; TSS Segment for X64 specially
80 TssSeg LABEL QWORD
81 DW TSS_DESC_SIZE - 1 ; LimitLow
82 DW 0 ; BaseLow
83 DB 0 ; BaseMid
84 DB 89h
85 DB 00h ; LimitHigh
86 DB 0 ; BaseHigh
87 DD 0 ; BaseUpper
88 DD 0 ; Reserved
89 GDT_SIZE = $ - offset NullSeg
90
91 ; Create TSS Descriptor just after GDT
92 TssDescriptor LABEL BYTE
93 DD 0 ; Reserved
94 DQ 0 ; RSP0
95 DQ 0 ; RSP1
96 DQ 0 ; RSP2
97 DD 0 ; Reserved
98 DD 0 ; Reserved
99 DQ 0 ; IST1
100 DQ 0 ; IST2
101 DQ 0 ; IST3
102 DQ 0 ; IST4
103 DQ 0 ; IST5
104 DQ 0 ; IST6
105 DQ 0 ; IST7
106 DD 0 ; Reserved
107 DD 0 ; Reserved
108 DW 0 ; Reserved
109 DW 0 ; I/O Map Base Address
110 TSS_DESC_SIZE = $ - offset TssDescriptor
111
112 ;
113 ; This structure serves as a template for all processors.
114 ;
115 gcPsd LABEL BYTE
116 DB 'PSDSIG '
117 DW PSD_SIZE
118 DW 2
119 DW 1 SHL 2
120 DW CODE_SEL
121 DW DATA_SEL
122 DW DATA_SEL
123 DW DATA_SEL
124 DW 0
125 DQ 0
126 DQ 0
127 DQ 0 ; fixed in InitializeMpServiceData()
128 DQ offset NullSeg
129 DD GDT_SIZE
130 DD 0
131 DB 24 dup (0)
132 DQ offset gSmiMtrrs
133 PSD_SIZE = $ - offset gcPsd
134
135 ;
136 ; CODE & DATA segments for SMM runtime
137 ;
138 CODE_SEL = offset CodeSeg64 - offset NullSeg
139 DATA_SEL = offset DataSeg32 - offset NullSeg
140 CODE32_SEL = offset CodeSeg32 - offset NullSeg
141
142 gcSmiGdtr LABEL FWORD
143 DW GDT_SIZE - 1
144 DQ offset NullSeg
145
146 gcSmiIdtr LABEL FWORD
147 DW IDT_SIZE - 1
148 DQ offset _SmiIDT
149
150 .data
151
152 ;
153 ; Here is the IDT. There are 32 (not 255) entries in it since only processor
154 ; generated exceptions will be handled.
155 ;
156 _SmiIDT:
157 REPEAT 32
158 DW 0 ; Offset 0:15
159 DW CODE_SEL ; Segment selector
160 DB 0 ; Unused
161 DB 8eh ; Interrupt Gate, Present
162 DW 0 ; Offset 16:31
163 DQ 0 ; Offset 32:63
164 ENDM
165 _SmiIDTEnd:
166
167 IDT_SIZE = (offset _SmiIDTEnd - offset _SmiIDT)
168
169 .code
170
171 ;------------------------------------------------------------------------------
172 ; _SmiExceptionEntryPoints is the collection of exception entry points followed
173 ; by a common exception handler.
174 ;
175 ; Stack frame would be as follows as specified in IA32 manuals:
176 ;
177 ; +---------------------+ <-- 16-byte aligned ensured by processor
178 ; + Old SS +
179 ; +---------------------+
180 ; + Old RSP +
181 ; +---------------------+
182 ; + RFlags +
183 ; +---------------------+
184 ; + CS +
185 ; +---------------------+
186 ; + RIP +
187 ; +---------------------+
188 ; + Error Code +
189 ; +---------------------+
190 ; + Vector Number +
191 ; +---------------------+
192 ; + RBP +
193 ; +---------------------+ <-- RBP, 16-byte aligned
194 ;
195 ; RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
196 ;------------------------------------------------------------------------------
197 PageFaultIdtHandlerSmmProfile PROC
198 push 0eh ; Page Fault
199 test spl, 8 ; odd multiple of 8 => ErrCode present
200 jnz @F
201 push [rsp] ; duplicate INT# if no ErrCode
202 mov qword ptr [rsp + 8], 0
203 @@:
204 push rbp
205 mov rbp, rsp
206
207 ;
208 ; Since here the stack pointer is 16-byte aligned, so
209 ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
210 ; is 16-byte aligned
211 ;
212
213 ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
214 ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
215 push r15
216 push r14
217 push r13
218 push r12
219 push r11
220 push r10
221 push r9
222 push r8
223 push rax
224 push rcx
225 push rdx
226 push rbx
227 push qword ptr [rbp + 48] ; RSP
228 push qword ptr [rbp] ; RBP
229 push rsi
230 push rdi
231
232 ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
233 movzx rax, word ptr [rbp + 56]
234 push rax ; for ss
235 movzx rax, word ptr [rbp + 32]
236 push rax ; for cs
237 mov rax, ds
238 push rax
239 mov rax, es
240 push rax
241 mov rax, fs
242 push rax
243 mov rax, gs
244 push rax
245
246 ;; UINT64 Rip;
247 push qword ptr [rbp + 24]
248
249 ;; UINT64 Gdtr[2], Idtr[2];
250 sub rsp, 16
251 sidt fword ptr [rsp]
252 sub rsp, 16
253 sgdt fword ptr [rsp]
254
255 ;; UINT64 Ldtr, Tr;
256 xor rax, rax
257 str ax
258 push rax
259 sldt ax
260 push rax
261
262 ;; UINT64 RFlags;
263 push qword ptr [rbp + 40]
264
265 ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
266 mov rax, cr8
267 push rax
268 mov rax, cr4
269 or rax, 208h
270 mov cr4, rax
271 push rax
272 mov rax, cr3
273 push rax
274 mov rax, cr2
275 push rax
276 xor rax, rax
277 push rax
278 mov rax, cr0
279 push rax
280
281 ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
282 mov rax, dr7
283 push rax
284 mov rax, dr6
285 push rax
286 mov rax, dr3
287 push rax
288 mov rax, dr2
289 push rax
290 mov rax, dr1
291 push rax
292 mov rax, dr0
293 push rax
294
295 ;; FX_SAVE_STATE_X64 FxSaveState;
296
297 sub rsp, 512
298 mov rdi, rsp
299 db 0fh, 0aeh, 00000111y ;fxsave [rdi]
300
301 ; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
302 cld
303
304 ;; UINT32 ExceptionData;
305 push qword ptr [rbp + 16]
306
307 ;; call into exception handler
308 mov rcx, [rbp + 8]
309 mov rax, SmiPFHandler
310
311 ;; Prepare parameter and call
312 mov rdx, rsp
313 ;
314 ; Per X64 calling convention, allocate maximum parameter stack space
315 ; and make sure RSP is 16-byte aligned
316 ;
317 sub rsp, 4 * 8 + 8
318 call rax
319 add rsp, 4 * 8 + 8
320 jmp @F
321
322 @@:
323 ;; UINT64 ExceptionData;
324 add rsp, 8
325
326 ;; FX_SAVE_STATE_X64 FxSaveState;
327
328 mov rsi, rsp
329 db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
330 add rsp, 512
331
332 ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
333 ;; Skip restoration of DRx registers to support debuggers
334 ;; that set breakpoints in interrupt/exception context
335 add rsp, 8 * 6
336
337 ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
338 pop rax
339 mov cr0, rax
340 add rsp, 8 ; not for Cr1
341 pop rax
342 mov cr2, rax
343 pop rax
344 mov cr3, rax
345 pop rax
346 mov cr4, rax
347 pop rax
348 mov cr8, rax
349
350 ;; UINT64 RFlags;
351 pop qword ptr [rbp + 40]
352
353 ;; UINT64 Ldtr, Tr;
354 ;; UINT64 Gdtr[2], Idtr[2];
355 ;; Best not let anyone mess with these particular registers...
356 add rsp, 48
357
358 ;; UINT64 Rip;
359 pop qword ptr [rbp + 24]
360
361 ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
362 pop rax
363 ; mov gs, rax ; not for gs
364 pop rax
365 ; mov fs, rax ; not for fs
366 ; (X64 will not use fs and gs, so we do not restore it)
367 pop rax
368 mov es, rax
369 pop rax
370 mov ds, rax
371 pop qword ptr [rbp + 32] ; for cs
372 pop qword ptr [rbp + 56] ; for ss
373
374 ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
375 ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
376 pop rdi
377 pop rsi
378 add rsp, 8 ; not for rbp
379 pop qword ptr [rbp + 48] ; for rsp
380 pop rbx
381 pop rdx
382 pop rcx
383 pop rax
384 pop r8
385 pop r9
386 pop r10
387 pop r11
388 pop r12
389 pop r13
390 pop r14
391 pop r15
392
393 mov rsp, rbp
394
395 ; Enable TF bit after page fault handler runs
396 bts dword ptr [rsp + 40], 8 ;RFLAGS
397
398 pop rbp
399 add rsp, 16 ; skip INT# & ErrCode
400 iretq
401 PageFaultIdtHandlerSmmProfile ENDP
402
403 InitializeIDTSmmStackGuard PROC
404 ;
405 ; If SMM Stack Guard feature is enabled, set the IST field of
406 ; the interrupt gate for Page Fault Exception to be 1
407 ;
408 lea rax, _SmiIDT + 14 * 16
409 mov byte ptr [rax + 4], 1
410 ret
411 InitializeIDTSmmStackGuard ENDP
412
413 END