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