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