]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiException.asm
UefiCpuPkg/PiSmmCpuDxeSmm: Add paging protection.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiException.asm
CommitLineData
427e3573 1;------------------------------------------------------------------------------ ;\r
717fb604 2; Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
427e3573
MK
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
717fb604
JY
147 DW 0\r
148 DQ 0\r
427e3573
MK
149\r
150 .code\r
151\r
152;------------------------------------------------------------------------------\r
153; _SmiExceptionEntryPoints is the collection of exception entry points followed\r
154; by a common exception handler.\r
155;\r
156; Stack frame would be as follows as specified in IA32 manuals:\r
157;\r
158; +---------------------+ <-- 16-byte aligned ensured by processor\r
159; + Old SS +\r
160; +---------------------+\r
161; + Old RSP +\r
162; +---------------------+\r
163; + RFlags +\r
164; +---------------------+\r
165; + CS +\r
166; +---------------------+\r
167; + RIP +\r
168; +---------------------+\r
169; + Error Code +\r
170; +---------------------+\r
171; + Vector Number +\r
172; +---------------------+\r
173; + RBP +\r
174; +---------------------+ <-- RBP, 16-byte aligned\r
175;\r
176; RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT\r
177;------------------------------------------------------------------------------\r
178PageFaultIdtHandlerSmmProfile PROC\r
179 push 0eh ; Page Fault\r
180 test spl, 8 ; odd multiple of 8 => ErrCode present\r
181 jnz @F\r
182 push [rsp] ; duplicate INT# if no ErrCode\r
183 mov qword ptr [rsp + 8], 0\r
184@@:\r
185 push rbp\r
186 mov rbp, rsp\r
187\r
188 ;\r
189 ; Since here the stack pointer is 16-byte aligned, so\r
190 ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
191 ; is 16-byte aligned\r
192 ;\r
193\r
194;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
195;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
196 push r15\r
197 push r14\r
198 push r13\r
199 push r12\r
200 push r11\r
201 push r10\r
202 push r9\r
203 push r8\r
204 push rax\r
205 push rcx\r
206 push rdx\r
207 push rbx\r
208 push qword ptr [rbp + 48] ; RSP\r
209 push qword ptr [rbp] ; RBP\r
210 push rsi\r
211 push rdi\r
212\r
213;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
214 movzx rax, word ptr [rbp + 56]\r
215 push rax ; for ss\r
216 movzx rax, word ptr [rbp + 32]\r
217 push rax ; for cs\r
218 mov rax, ds\r
219 push rax\r
220 mov rax, es\r
221 push rax\r
222 mov rax, fs\r
223 push rax\r
224 mov rax, gs\r
225 push rax\r
226\r
227;; UINT64 Rip;\r
228 push qword ptr [rbp + 24]\r
229\r
230;; UINT64 Gdtr[2], Idtr[2];\r
231 sub rsp, 16\r
232 sidt fword ptr [rsp]\r
233 sub rsp, 16\r
234 sgdt fword ptr [rsp]\r
235\r
236;; UINT64 Ldtr, Tr;\r
237 xor rax, rax\r
238 str ax\r
239 push rax\r
240 sldt ax\r
241 push rax\r
242\r
243;; UINT64 RFlags;\r
244 push qword ptr [rbp + 40]\r
245\r
246;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
247 mov rax, cr8\r
248 push rax\r
249 mov rax, cr4\r
250 or rax, 208h\r
251 mov cr4, rax\r
252 push rax\r
253 mov rax, cr3\r
254 push rax\r
255 mov rax, cr2\r
256 push rax\r
257 xor rax, rax\r
258 push rax\r
259 mov rax, cr0\r
260 push rax\r
261\r
262;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
263 mov rax, dr7\r
264 push rax\r
265 mov rax, dr6\r
266 push rax\r
267 mov rax, dr3\r
268 push rax\r
269 mov rax, dr2\r
270 push rax\r
271 mov rax, dr1\r
272 push rax\r
273 mov rax, dr0\r
274 push rax\r
275\r
276;; FX_SAVE_STATE_X64 FxSaveState;\r
277\r
278 sub rsp, 512\r
279 mov rdi, rsp\r
280 db 0fh, 0aeh, 00000111y ;fxsave [rdi]\r
281\r
282; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
283 cld\r
284\r
285;; UINT32 ExceptionData;\r
286 push qword ptr [rbp + 16]\r
287\r
288;; call into exception handler\r
289 mov rcx, [rbp + 8]\r
290 mov rax, SmiPFHandler\r
291\r
292;; Prepare parameter and call\r
293 mov rdx, rsp\r
294 ;\r
295 ; Per X64 calling convention, allocate maximum parameter stack space\r
296 ; and make sure RSP is 16-byte aligned\r
297 ;\r
298 sub rsp, 4 * 8 + 8\r
299 call rax\r
300 add rsp, 4 * 8 + 8\r
301 jmp @F\r
302\r
303@@:\r
304;; UINT64 ExceptionData;\r
305 add rsp, 8\r
306\r
307;; FX_SAVE_STATE_X64 FxSaveState;\r
308\r
309 mov rsi, rsp\r
310 db 0fh, 0aeh, 00001110y ; fxrstor [rsi]\r
311 add rsp, 512\r
312\r
313;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
314;; Skip restoration of DRx registers to support debuggers\r
315;; that set breakpoints in interrupt/exception context\r
316 add rsp, 8 * 6\r
317\r
318;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
319 pop rax\r
320 mov cr0, rax\r
321 add rsp, 8 ; not for Cr1\r
322 pop rax\r
323 mov cr2, rax\r
324 pop rax\r
325 mov cr3, rax\r
326 pop rax\r
327 mov cr4, rax\r
328 pop rax\r
329 mov cr8, rax\r
330\r
331;; UINT64 RFlags;\r
332 pop qword ptr [rbp + 40]\r
333\r
334;; UINT64 Ldtr, Tr;\r
335;; UINT64 Gdtr[2], Idtr[2];\r
336;; Best not let anyone mess with these particular registers...\r
337 add rsp, 48\r
338\r
339;; UINT64 Rip;\r
340 pop qword ptr [rbp + 24]\r
341\r
342;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
343 pop rax\r
344 ; mov gs, rax ; not for gs\r
345 pop rax\r
346 ; mov fs, rax ; not for fs\r
347 ; (X64 will not use fs and gs, so we do not restore it)\r
348 pop rax\r
349 mov es, rax\r
350 pop rax\r
351 mov ds, rax\r
352 pop qword ptr [rbp + 32] ; for cs\r
353 pop qword ptr [rbp + 56] ; for ss\r
354\r
355;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
356;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
357 pop rdi\r
358 pop rsi\r
359 add rsp, 8 ; not for rbp\r
360 pop qword ptr [rbp + 48] ; for rsp\r
361 pop rbx\r
362 pop rdx\r
363 pop rcx\r
364 pop rax\r
365 pop r8\r
366 pop r9\r
367 pop r10\r
368 pop r11\r
369 pop r12\r
370 pop r13\r
371 pop r14\r
372 pop r15\r
373\r
374 mov rsp, rbp\r
375\r
376; Enable TF bit after page fault handler runs\r
377 bts dword ptr [rsp + 40], 8 ;RFLAGS\r
378\r
379 pop rbp\r
380 add rsp, 16 ; skip INT# & ErrCode\r
381 iretq\r
382PageFaultIdtHandlerSmmProfile ENDP\r
383\r
427e3573 384 END\r