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