]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiException.S
6dbcaa5b671490d53ca0388fd73730377bd56fd4
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiException.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2009 - 2015, 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 # LimitLow
83 .word 0 # BaseLow
84 .byte 0 # BaseMid
85 .byte 0x89
86 .byte 0xDB # 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 IDT_SIZE - 1
132 .quad _SmiIDT
133
134
135 #
136 # Here is the IDT. There are 32 (not 255) entries in it since only processor
137 # generated exceptions will be handled.
138 #
139 _SmiIDT:
140 # The following segment repeats 32 times:
141 # No. 1
142 .word 0 # Offset 0:15
143 .word CODE_SEL
144 .byte 0 # Unused
145 .byte 0x8e # Interrupt Gate, Present
146 .word 0 # Offset 16:31
147 .quad 0 # Offset 32:63
148 # No. 2
149 .word 0 # Offset 0:15
150 .word CODE_SEL
151 .byte 0 # Unused
152 .byte 0x8e # Interrupt Gate, Present
153 .word 0 # Offset 16:31
154 .quad 0 # Offset 32:63
155 # No. 3
156 .word 0 # Offset 0:15
157 .word CODE_SEL
158 .byte 0 # Unused
159 .byte 0x8e # Interrupt Gate, Present
160 .word 0 # Offset 16:31
161 .quad 0 # Offset 32:63
162 # No. 4
163 .word 0 # Offset 0:15
164 .word CODE_SEL
165 .byte 0 # Unused
166 .byte 0x8e # Interrupt Gate, Present
167 .word 0 # Offset 16:31
168 .quad 0 # Offset 32:63
169 # No. 5
170 .word 0 # Offset 0:15
171 .word CODE_SEL
172 .byte 0 # Unused
173 .byte 0x8e # Interrupt Gate, Present
174 .word 0 # Offset 16:31
175 .quad 0 # Offset 32:63
176 # No. 6
177 .word 0 # Offset 0:15
178 .word CODE_SEL
179 .byte 0 # Unused
180 .byte 0x8e # Interrupt Gate, Present
181 .word 0 # Offset 16:31
182 .quad 0 # Offset 32:63
183 # No. 7
184 .word 0 # Offset 0:15
185 .word CODE_SEL
186 .byte 0 # Unused
187 .byte 0x8e # Interrupt Gate, Present
188 .word 0 # Offset 16:31
189 .quad 0 # Offset 32:63
190 # No. 8
191 .word 0 # Offset 0:15
192 .word CODE_SEL
193 .byte 0 # Unused
194 .byte 0x8e # Interrupt Gate, Present
195 .word 0 # Offset 16:31
196 .quad 0 # Offset 32:63
197 # No. 9
198 .word 0 # Offset 0:15
199 .word CODE_SEL
200 .byte 0 # Unused
201 .byte 0x8e # Interrupt Gate, Present
202 .word 0 # Offset 16:31
203 .quad 0 # Offset 32:63
204 # No. 10
205 .word 0 # Offset 0:15
206 .word CODE_SEL
207 .byte 0 # Unused
208 .byte 0x8e # Interrupt Gate, Present
209 .word 0 # Offset 16:31
210 .quad 0 # Offset 32:63
211 # No. 11
212 .word 0 # Offset 0:15
213 .word CODE_SEL
214 .byte 0 # Unused
215 .byte 0x8e # Interrupt Gate, Present
216 .word 0 # Offset 16:31
217 .quad 0 # Offset 32:63
218 # No. 12
219 .word 0 # Offset 0:15
220 .word CODE_SEL
221 .byte 0 # Unused
222 .byte 0x8e # Interrupt Gate, Present
223 .word 0 # Offset 16:31
224 .quad 0 # Offset 32:63
225 # No. 13
226 .word 0 # Offset 0:15
227 .word CODE_SEL
228 .byte 0 # Unused
229 .byte 0x8e # Interrupt Gate, Present
230 .word 0 # Offset 16:31
231 .quad 0 # Offset 32:63
232 # No. 14
233 .word 0 # Offset 0:15
234 .word CODE_SEL
235 .byte 0 # Unused
236 .byte 0x8e # Interrupt Gate, Present
237 .word 0 # Offset 16:31
238 .quad 0 # Offset 32:63
239 # No. 15
240 .word 0 # Offset 0:15
241 .word CODE_SEL
242 .byte 0 # Unused
243 .byte 0x8e # Interrupt Gate, Present
244 .word 0 # Offset 16:31
245 .quad 0 # Offset 32:63
246 # No. 16
247 .word 0 # Offset 0:15
248 .word CODE_SEL
249 .byte 0 # Unused
250 .byte 0x8e # Interrupt Gate, Present
251 .word 0 # Offset 16:31
252 .quad 0 # Offset 32:63
253 # No. 17
254 .word 0 # Offset 0:15
255 .word CODE_SEL
256 .byte 0 # Unused
257 .byte 0x8e # Interrupt Gate, Present
258 .word 0 # Offset 16:31
259 .quad 0 # Offset 32:63
260 # No. 18
261 .word 0 # Offset 0:15
262 .word CODE_SEL
263 .byte 0 # Unused
264 .byte 0x8e # Interrupt Gate, Present
265 .word 0 # Offset 16:31
266 .quad 0 # Offset 32:63
267 # No. 19
268 .word 0 # Offset 0:15
269 .word CODE_SEL
270 .byte 0 # Unused
271 .byte 0x8e # Interrupt Gate, Present
272 .word 0 # Offset 16:31
273 .quad 0 # Offset 32:63
274 # No. 20
275 .word 0 # Offset 0:15
276 .word CODE_SEL
277 .byte 0 # Unused
278 .byte 0x8e # Interrupt Gate, Present
279 .word 0 # Offset 16:31
280 .quad 0 # Offset 32:63
281 # No. 21
282 .word 0 # Offset 0:15
283 .word CODE_SEL
284 .byte 0 # Unused
285 .byte 0x8e # Interrupt Gate, Present
286 .word 0 # Offset 16:31
287 .quad 0 # Offset 32:63
288 # No. 22
289 .word 0 # Offset 0:15
290 .word CODE_SEL
291 .byte 0 # Unused
292 .byte 0x8e # Interrupt Gate, Present
293 .word 0 # Offset 16:31
294 .quad 0 # Offset 32:63
295 # No. 23
296 .word 0 # Offset 0:15
297 .word CODE_SEL
298 .byte 0 # Unused
299 .byte 0x8e # Interrupt Gate, Present
300 .word 0 # Offset 16:31
301 .quad 0 # Offset 32:63
302 # No. 24
303 .word 0 # Offset 0:15
304 .word CODE_SEL
305 .byte 0 # Unused
306 .byte 0x8e # Interrupt Gate, Present
307 .word 0 # Offset 16:31
308 .quad 0 # Offset 32:63
309 # No. 25
310 .word 0 # Offset 0:15
311 .word CODE_SEL
312 .byte 0 # Unused
313 .byte 0x8e # Interrupt Gate, Present
314 .word 0 # Offset 16:31
315 .quad 0 # Offset 32:63
316 # No. 26
317 .word 0 # Offset 0:15
318 .word CODE_SEL
319 .byte 0 # Unused
320 .byte 0x8e # Interrupt Gate, Present
321 .word 0 # Offset 16:31
322 .quad 0 # Offset 32:63
323 # No. 27
324 .word 0 # Offset 0:15
325 .word CODE_SEL
326 .byte 0 # Unused
327 .byte 0x8e # Interrupt Gate, Present
328 .word 0 # Offset 16:31
329 .quad 0 # Offset 32:63
330 # No. 28
331 .word 0 # Offset 0:15
332 .word CODE_SEL
333 .byte 0 # Unused
334 .byte 0x8e # Interrupt Gate, Present
335 .word 0 # Offset 16:31
336 .quad 0 # Offset 32:63
337 # No. 29
338 .word 0 # Offset 0:15
339 .word CODE_SEL
340 .byte 0 # Unused
341 .byte 0x8e # Interrupt Gate, Present
342 .word 0 # Offset 16:31
343 .quad 0 # Offset 32:63
344 # No. 30
345 .word 0 # Offset 0:15
346 .word CODE_SEL
347 .byte 0 # Unused
348 .byte 0x8e # Interrupt Gate, Present
349 .word 0 # Offset 16:31
350 .quad 0 # Offset 32:63
351 # No. 31
352 .word 0 # Offset 0:15
353 .word CODE_SEL
354 .byte 0 # Unused
355 .byte 0x8e # Interrupt Gate, Present
356 .word 0 # Offset 16:31
357 .quad 0 # Offset 32:63
358 # No. 32
359 .word 0 # Offset 0:15
360 .word CODE_SEL
361 .byte 0 # Unused
362 .byte 0x8e # Interrupt Gate, Present
363 .word 0 # Offset 16:31
364 .quad 0 # Offset 32:63
365
366 _SmiIDTEnd:
367
368 .equ IDT_SIZE, (_SmiIDTEnd - _SmiIDT)
369
370 .text
371
372 #------------------------------------------------------------------------------
373 # _SmiExceptionEntryPoints is the collection of exception entry points followed
374 # by a common exception handler.
375 #
376 # Stack frame would be as follows as specified in IA32 manuals:
377 # +---------------------+ <-- 16-byte aligned ensured by processor
378 # + Old SS +
379 # +---------------------+
380 # + Old RSP +
381 # +---------------------+
382 # + RFlags +
383 # +---------------------+
384 # + CS +
385 # +---------------------+
386 # + RIP +
387 # +---------------------+
388 # + Error Code +
389 # +---------------------+
390 # + Vector Number +
391 # +---------------------+
392 # + RBP +
393 # +---------------------+ <-- RBP, 16-byte aligned
394 #
395 # RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
396 #------------------------------------------------------------------------------
397 ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
398 ASM_PFX(PageFaultIdtHandlerSmmProfile):
399 pushq $0x0e # Page Fault
400 .byte 0x40, 0xf6, 0xc4, 0x08 #test spl, 8
401 jnz L1
402 pushq (%rsp)
403 movq $0, 8(%rsp)
404 L1:
405 pushq %rbp
406 movq %rsp, %rbp
407
408 #
409 # Since here the stack pointer is 16-byte aligned, so
410 # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
411 # is 16-byte aligned
412 #
413
414 ## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
415 ## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
416 pushq %r15
417 pushq %r14
418 pushq %r13
419 pushq %r12
420 pushq %r11
421 pushq %r10
422 pushq %r9
423 pushq %r8
424 pushq %rax
425 pushq %rcx
426 pushq %rdx
427 pushq %rbx
428 pushq 48(%rbp) # RSP
429 pushq (%rbp) # RBP
430 pushq %rsi
431 pushq %rdi
432
433 ## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
434 movzwq 56(%rbp), %rax
435 pushq %rax # for ss
436 movzwq 32(%rbp), %rax
437 pushq %rax # for cs
438 movq %ds, %rax
439 pushq %rax
440 movq %es, %rax
441 pushq %rax
442 movq %fs, %rax
443 pushq %rax
444 movq %gs, %rax
445 pushq %rax
446
447 ## UINT64 Rip;
448 pushq 24(%rbp)
449
450 ## UINT64 Gdtr[2], Idtr[2];
451 subq $16, %rsp
452 sidt (%rsp)
453 subq $16, %rsp
454 sgdt (%rsp)
455
456 ## UINT64 Ldtr, Tr;
457 xorq %rax, %rax
458 strw %ax
459 pushq %rax
460 sldtw %ax
461 pushq %rax
462
463 ## UINT64 RFlags;
464 pushq 40(%rbp)
465
466 ## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
467 movq %cr8, %rax
468 pushq %rax
469 movq %cr4, %rax
470 orq $0x208, %rax
471 movq %rax, %cr4
472 pushq %rax
473 movq %cr3, %rax
474 pushq %rax
475 movq %cr2, %rax
476 pushq %rax
477 xorq %rax, %rax
478 pushq %rax
479 movq %cr0, %rax
480 pushq %rax
481
482 ## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
483 movq %dr7, %rax
484 pushq %rax
485 movq %dr6, %rax
486 pushq %rax
487 movq %dr3, %rax
488 pushq %rax
489 movq %dr2, %rax
490 pushq %rax
491 movq %dr1, %rax
492 pushq %rax
493 movq %dr0, %rax
494 pushq %rax
495
496 ## FX_SAVE_STATE_X64 FxSaveState;
497
498 subq $512, %rsp
499 movq %rsp, %rdi
500 .byte 0xf, 0xae, 0x7 # fxsave [rdi]
501
502 # UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
503 cld
504
505 ## UINT32 ExceptionData;
506 pushq 16(%rbp)
507
508 ## call into exception handler
509 movq 8(%rbp), %rcx
510 movabsq $ASM_PFX(SmiPFHandler), %rax
511
512 ## Prepare parameter and call
513 movq %rsp, %rdx
514 #
515 # Per X64 calling convention, allocate maximum parameter stack space
516 # and make sure RSP is 16-byte aligned
517 #
518 subq $4 * 8 + 8, %rsp
519 call *%rax
520 addq $4 * 8 + 8, %rsp
521 jmp L5
522
523 L5:
524 ## UINT64 ExceptionData;
525 addq $8, %rsp
526
527 ## FX_SAVE_STATE_X64 FxSaveState;
528
529 movq %rsp, %rsi
530 .byte 0xf, 0xae, 0xe # fxrstor [rsi]
531 addq $512, %rsp
532
533 ## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
534 ## Skip restoration of DRx registers to support debuggers
535 ## that set breakpoints in interrupt/exception context
536 addq $8 * 6, %rsp
537
538 ## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
539 popq %rax
540 movq %rax, %cr0
541 addq $8, %rsp # not for Cr1
542 popq %rax
543 movq %rax, %cr2
544 popq %rax
545 movq %rax, %cr3
546 popq %rax
547 movq %rax, %cr4
548 popq %rax
549 movq %rax, %cr8
550
551 ## UINT64 RFlags;
552 popq 40(%rbp)
553
554 ## UINT64 Ldtr, Tr;
555 ## UINT64 Gdtr[2], Idtr[2];
556 ## Best not let anyone mess with these particular registers...
557 addq $48, %rsp
558
559 ## UINT64 Rip;
560 popq 24(%rbp)
561
562 ## UINT64 Gs, Fs, Es, Ds, Cs, Ss;
563 popq %rax
564 # mov gs, rax ; not for gs
565 popq %rax
566 # mov fs, rax ; not for fs
567 # (X64 will not use fs and gs, so we do not restore it)
568 popq %rax
569 movq %rax, %es
570 popq %rax
571 movq %rax, %ds
572 popq 32(%rbp) # for cs
573 popq 56(%rbp) # for ss
574
575 ## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
576 ## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
577 popq %rdi
578 popq %rsi
579 addq $8, %rsp # not for rbp
580 popq 48(%rbp) # for rsp
581 popq %rbx
582 popq %rdx
583 popq %rcx
584 popq %rax
585 popq %r8
586 popq %r9
587 popq %r10
588 popq %r11
589 popq %r12
590 popq %r13
591 popq %r14
592 popq %r15
593
594 movq %rbp, %rsp
595
596 # Enable TF bit after page fault handler runs
597 btsl $8, 40(%rsp) #RFLAGS
598
599 popq %rbp
600 addq $16, %rsp # skip INT# & ErrCode
601 iretq
602
603 ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard)
604 ASM_PFX(InitializeIDTSmmStackGuard):
605 # If SMM Stack Guard feature is enabled, set the IST field of
606 # the interrupt gate for Page Fault Exception to be 1
607 #
608 movabsq $_SmiIDT + 14 * 16, %rax
609 movb $1, 4(%rax)
610 ret