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