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