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