MdePkg/BaseLib: add PatchInstructionX86()
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiException.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials
5 # are licensed and made available under the terms and conditions of the BSD License
6 # which accompanies this distribution. The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
8 #
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #
12 # Module Name:
13 #
14 # SmiException.S
15 #
16 # Abstract:
17 #
18 # Exception handlers used in SM mode
19 #
20 #------------------------------------------------------------------------------
21
22 ASM_GLOBAL ASM_PFX(SmiPFHandler)
23 ASM_GLOBAL ASM_PFX(gcSmiIdtr)
24 ASM_GLOBAL ASM_PFX(gcSmiGdtr)
25 ASM_GLOBAL ASM_PFX(gcPsd)
26
27 .data
28
29 NullSeg: .quad 0 # reserved by architecture
30 CodeSeg32:
31 .word -1 # LimitLow
32 .word 0 # BaseLow
33 .byte 0 # BaseMid
34 .byte 0x9b
35 .byte 0xcf # LimitHigh
36 .byte 0 # BaseHigh
37 ProtModeCodeSeg32:
38 .word -1 # LimitLow
39 .word 0 # BaseLow
40 .byte 0 # BaseMid
41 .byte 0x9b
42 .byte 0xcf # LimitHigh
43 .byte 0 # BaseHigh
44 ProtModeSsSeg32:
45 .word -1 # LimitLow
46 .word 0 # BaseLow
47 .byte 0 # BaseMid
48 .byte 0x93
49 .byte 0xcf # LimitHigh
50 .byte 0 # BaseHigh
51 DataSeg32:
52 .word -1 # LimitLow
53 .word 0 # BaseLow
54 .byte 0 # BaseMid
55 .byte 0x93
56 .byte 0xcf # LimitHigh
57 .byte 0 # BaseHigh
58 CodeSeg16:
59 .word -1
60 .word 0
61 .byte 0
62 .byte 0x9b
63 .byte 0x8f
64 .byte 0
65 DataSeg16:
66 .word -1
67 .word 0
68 .byte 0
69 .byte 0x93
70 .byte 0x8f
71 .byte 0
72 CodeSeg64:
73 .word -1 # LimitLow
74 .word 0 # BaseLow
75 .byte 0 # BaseMid
76 .byte 0x9b
77 .byte 0xaf # LimitHigh
78 .byte 0 # BaseHigh
79 # TSS Segment for X64 specially
80 TssSeg:
81 .word TSS_DESC_SIZE - 1 # LimitLow
82 .word 0 # BaseLow
83 .byte 0 # BaseMid
84 .byte 0x89
85 .byte 0x00 # LimitHigh
86 .byte 0 # BaseHigh
87 .long 0 # BaseUpper
88 .long 0 # Reserved
89 .equ GDT_SIZE, .- NullSeg
90
91 TssDescriptor:
92 .space 104, 0
93 .equ TSS_DESC_SIZE, .- TssDescriptor
94
95 #
96 # This structure serves as a template for all processors.
97 #
98 ASM_PFX(gcPsd):
99 .ascii "PSDSIG "
100 .word PSD_SIZE
101 .word 2
102 .word 1 << 2
103 .word CODE_SEL
104 .word DATA_SEL
105 .word DATA_SEL
106 .word DATA_SEL
107 .word 0
108 .quad 0
109 .quad 0
110 .quad 0 # fixed in InitializeMpServiceData()
111 .quad NullSeg
112 .long GDT_SIZE
113 .long 0
114 .space 24, 0
115 .quad 0
116 .equ PSD_SIZE, . - ASM_PFX(gcPsd)
117
118 #
119 # CODE & DATA segments for SMM runtime
120 #
121 .equ CODE_SEL, CodeSeg64 - NullSeg
122 .equ DATA_SEL, DataSeg32 - NullSeg
123 .equ CODE32_SEL, CodeSeg32 - NullSeg
124
125 ASM_PFX(gcSmiGdtr):
126 .word GDT_SIZE - 1
127 .quad NullSeg
128
129 ASM_PFX(gcSmiIdtr):
130 .word 0
131 .quad 0
132
133 .text
134
135 #------------------------------------------------------------------------------
136 # _SmiExceptionEntryPoints is the collection of exception entry points followed
137 # by a common exception handler.
138 #
139 # Stack frame would be as follows as specified in IA32 manuals:
140 # +---------------------+ <-- 16-byte aligned ensured by processor
141 # + Old SS +
142 # +---------------------+
143 # + Old RSP +
144 # +---------------------+
145 # + RFlags +
146 # +---------------------+
147 # + CS +
148 # +---------------------+
149 # + RIP +
150 # +---------------------+
151 # + Error Code +
152 # +---------------------+
153 # + Vector Number +
154 # +---------------------+
155 # + RBP +
156 # +---------------------+ <-- RBP, 16-byte aligned
157 #
158 # RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
159 #------------------------------------------------------------------------------
160 ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
161 ASM_PFX(PageFaultIdtHandlerSmmProfile):
162 pushq $0x0e # Page Fault
163 .byte 0x40, 0xf6, 0xc4, 0x08 #test spl, 8
164 jnz L1
165 pushq (%rsp)
166 movq $0, 8(%rsp)
167 L1:
168 pushq %rbp
169 movq %rsp, %rbp
170
171 #
172 # Since here the stack pointer is 16-byte aligned, so
173 # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
174 # is 16-byte aligned
175 #
176
177 ## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
178 ## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
179 pushq %r15
180 pushq %r14
181 pushq %r13
182 pushq %r12
183 pushq %r11
184 pushq %r10
185 pushq %r9
186 pushq %r8
187 pushq %rax
188 pushq %rcx
189 pushq %rdx
190 pushq %rbx
191 pushq 48(%rbp) # RSP
192 pushq (%rbp) # RBP
193 pushq %rsi
194 pushq %rdi
195
196 ## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
197 movzwq 56(%rbp), %rax
198 pushq %rax # for ss
199 movzwq 32(%rbp), %rax
200 pushq %rax # for cs
201 movq %ds, %rax
202 pushq %rax
203 movq %es, %rax
204 pushq %rax
205 movq %fs, %rax
206 pushq %rax
207 movq %gs, %rax
208 pushq %rax
209
210 ## UINT64 Rip;
211 pushq 24(%rbp)
212
213 ## UINT64 Gdtr[2], Idtr[2];
214 subq $16, %rsp
215 sidt (%rsp)
216 subq $16, %rsp
217 sgdt (%rsp)
218
219 ## UINT64 Ldtr, Tr;
220 xorq %rax, %rax
221 strw %ax
222 pushq %rax
223 sldtw %ax
224 pushq %rax
225
226 ## UINT64 RFlags;
227 pushq 40(%rbp)
228
229 ## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
230 movq %cr8, %rax
231 pushq %rax
232 movq %cr4, %rax
233 orq $0x208, %rax
234 movq %rax, %cr4
235 pushq %rax
236 movq %cr3, %rax
237 pushq %rax
238 movq %cr2, %rax
239 pushq %rax
240 xorq %rax, %rax
241 pushq %rax
242 movq %cr0, %rax
243 pushq %rax
244
245 ## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
246 movq %dr7, %rax
247 pushq %rax
248 movq %dr6, %rax
249 pushq %rax
250 movq %dr3, %rax
251 pushq %rax
252 movq %dr2, %rax
253 pushq %rax
254 movq %dr1, %rax
255 pushq %rax
256 movq %dr0, %rax
257 pushq %rax
258
259 ## FX_SAVE_STATE_X64 FxSaveState;
260
261 subq $512, %rsp
262 movq %rsp, %rdi
263 .byte 0xf, 0xae, 0x7 # fxsave [rdi]
264
265 # UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
266 cld
267
268 ## UINT32 ExceptionData;
269 pushq 16(%rbp)
270
271 ## call into exception handler
272 movq 8(%rbp), %rcx
273 movabsq $ASM_PFX(SmiPFHandler), %rax
274
275 ## Prepare parameter and call
276 movq %rsp, %rdx
277 #
278 # Per X64 calling convention, allocate maximum parameter stack space
279 # and make sure RSP is 16-byte aligned
280 #
281 subq $4 * 8 + 8, %rsp
282 call *%rax
283 addq $4 * 8 + 8, %rsp
284 jmp L5
285
286 L5:
287 ## UINT64 ExceptionData;
288 addq $8, %rsp
289
290 ## FX_SAVE_STATE_X64 FxSaveState;
291
292 movq %rsp, %rsi
293 .byte 0xf, 0xae, 0xe # fxrstor [rsi]
294 addq $512, %rsp
295
296 ## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
297 ## Skip restoration of DRx registers to support debuggers
298 ## that set breakpoints in interrupt/exception context
299 addq $8 * 6, %rsp
300
301 ## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
302 popq %rax
303 movq %rax, %cr0
304 addq $8, %rsp # not for Cr1
305 popq %rax
306 movq %rax, %cr2
307 popq %rax
308 movq %rax, %cr3
309 popq %rax
310 movq %rax, %cr4
311 popq %rax
312 movq %rax, %cr8
313
314 ## UINT64 RFlags;
315 popq 40(%rbp)
316
317 ## UINT64 Ldtr, Tr;
318 ## UINT64 Gdtr[2], Idtr[2];
319 ## Best not let anyone mess with these particular registers...
320 addq $48, %rsp
321
322 ## UINT64 Rip;
323 popq 24(%rbp)
324
325 ## UINT64 Gs, Fs, Es, Ds, Cs, Ss;
326 popq %rax
327 # mov gs, rax ; not for gs
328 popq %rax
329 # mov fs, rax ; not for fs
330 # (X64 will not use fs and gs, so we do not restore it)
331 popq %rax
332 movq %rax, %es
333 popq %rax
334 movq %rax, %ds
335 popq 32(%rbp) # for cs
336 popq 56(%rbp) # for ss
337
338 ## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
339 ## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
340 popq %rdi
341 popq %rsi
342 addq $8, %rsp # not for rbp
343 popq 48(%rbp) # for rsp
344 popq %rbx
345 popq %rdx
346 popq %rcx
347 popq %rax
348 popq %r8
349 popq %r9
350 popq %r10
351 popq %r11
352 popq %r12
353 popq %r13
354 popq %r14
355 popq %r15
356
357 movq %rbp, %rsp
358
359 # Enable TF bit after page fault handler runs
360 btsl $8, 40(%rsp) #RFLAGS
361
362 popq %rbp
363 addq $16, %rsp # skip INT# & ErrCode
364 iretq
365