]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.S
cf5ef8217f63c9bc957220510f87306087dd39d9
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / 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(PageFaultStubFunction)
24 ASM_GLOBAL ASM_PFX(gSmiMtrrs)
25 ASM_GLOBAL ASM_PFX(gcSmiIdtr)
26 ASM_GLOBAL ASM_PFX(gcSmiGdtr)
27 ASM_GLOBAL ASM_PFX(gTaskGateDescriptor)
28 ASM_GLOBAL ASM_PFX(gcPsd)
29 ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
30
31 .data
32
33 NullSeg: .quad 0 # reserved by architecture
34 CodeSeg32:
35 .word -1 # LimitLow
36 .word 0 # BaseLow
37 .byte 0 # BaseMid
38 .byte 0x9b
39 .byte 0xcf # LimitHigh
40 .byte 0 # BaseHigh
41 ProtModeCodeSeg32:
42 .word -1 # LimitLow
43 .word 0 # BaseLow
44 .byte 0 # BaseMid
45 .byte 0x9b
46 .byte 0xcf # LimitHigh
47 .byte 0 # BaseHigh
48 ProtModeSsSeg32:
49 .word -1 # LimitLow
50 .word 0 # BaseLow
51 .byte 0 # BaseMid
52 .byte 0x93
53 .byte 0xcf # LimitHigh
54 .byte 0 # BaseHigh
55 DataSeg32:
56 .word -1 # LimitLow
57 .word 0 # BaseLow
58 .byte 0 # BaseMid
59 .byte 0x93
60 .byte 0xcf # LimitHigh
61 .byte 0 # BaseHigh
62 CodeSeg16:
63 .word -1
64 .word 0
65 .byte 0
66 .byte 0x9b
67 .byte 0x8f
68 .byte 0
69 DataSeg16:
70 .word -1
71 .word 0
72 .byte 0
73 .byte 0x93
74 .byte 0x8f
75 .byte 0
76 CodeSeg64:
77 .word -1 # LimitLow
78 .word 0 # BaseLow
79 .byte 0 # BaseMid
80 .byte 0x9b
81 .byte 0xaf # LimitHigh
82 .byte 0 # BaseHigh
83 .equ GDT_SIZE, .- NullSeg
84
85 TssSeg:
86 .word TSS_DESC_SIZE -1 # LimitLow
87 .word 0 # BaseLow
88 .byte 0 # BaseMid
89 .byte 0x89
90 .byte 0x00 # LimitHigh
91 .byte 0 # BaseHigh
92 ExceptionTssSeg:
93 .word TSS_DESC_SIZE - 1 # LimitLow
94 .word 0 # BaseLow
95 .byte 0 # BaseMid
96 .byte 0x89
97 .byte 0x00 # LimitHigh
98 .byte 0 # BaseHigh
99
100 .equ CODE_SEL, CodeSeg32 - NullSeg
101 .equ DATA_SEL, DataSeg32 - NullSeg
102 .equ TSS_SEL, TssSeg - NullSeg
103 .equ EXCEPTION_TSS_SEL, ExceptionTssSeg - NullSeg
104
105 # IA32 TSS fields
106 .equ TSS_ESP0, 4
107 .equ TSS_SS0, 8
108 .equ TSS_ESP1, 12
109 .equ TSS_SS1, 16
110 .equ TSS_ESP2, 20
111 .equ TSS_SS2, 24
112 .equ TSS_CR3, 28
113 .equ TSS_EIP, 32
114 .equ TSS_EFLAGS, 36
115 .equ TSS_EAX, 40
116 .equ TSS_ECX, 44
117 .equ TSS_EDX, 48
118 .equ TSS_EBX, 52
119 .equ TSS_ESP, 56
120 .equ TSS_EBP, 60
121 .equ TSS_ESI, 64
122 .equ TSS_EDI, 68
123 .equ TSS_ES, 72
124 .equ TSS_CS, 76
125 .equ TSS_SS, 80
126 .equ TSS_DS, 84
127 .equ TSS_FS, 88
128 .equ TSS_GS, 92
129 .equ TSS_LDT, 96
130
131 # Create 2 TSS segments just after GDT
132 TssDescriptor:
133 .word 0 # PreviousTaskLink
134 .word 0 # Reserved
135 .long 0 # ESP0
136 .word 0 # SS0
137 .word 0 # Reserved
138 .long 0 # ESP1
139 .word 0 # SS1
140 .word 0 # Reserved
141 .long 0 # ESP2
142 .word 0 # SS2
143 .word 0 # Reserved
144 .long 0 # CR3
145 .long 0 # EIP
146 .long 0 # EFLAGS
147 .long 0 # EAX
148 .long 0 # ECX
149 .long 0 # EDX
150 .long 0 # EBX
151 .long 0 # ESP
152 .long 0 # EBP
153 .long 0 # ESI
154 .long 0 # EDI
155 .word 0 # ES
156 .word 0 # Reserved
157 .word 0 # CS
158 .word 0 # Reserved
159 .word 0 # SS
160 .word 0 # Reserved
161 .word 0 # DS
162 .word 0 # Reserved
163 .word 0 # FS
164 .word 0 # Reserved
165 .word 0 # GS
166 .word 0 # Reserved
167 .word 0 # LDT Selector
168 .word 0 # Reserved
169 .word 0 # T
170 .word 0 # I/O Map Base
171 .equ TSS_DESC_SIZE, . - TssDescriptor
172
173 ExceptionTssDescriptor:
174 .word 0 # PreviousTaskLink
175 .word 0 # Reserved
176 .long 0 # ESP0
177 .word 0 # SS0
178 .word 0 # Reserved
179 .long 0 # ESP1
180 .word 0 # SS1
181 .word 0 # Reserved
182 .long 0 # ESP2
183 .word 0 # SS2
184 .word 0 # Reserved
185 .long 0 # CR3
186 .long PFHandlerEntry # EIP
187 .long 00000002 # EFLAGS
188 .long 0 # EAX
189 .long 0 # ECX
190 .long 0 # EDX
191 .long 0 # EBX
192 .long 0 # ESP
193 .long 0 # EBP
194 .long 0 # ESI
195 .long 0 # EDI
196 .word DATA_SEL # ES
197 .word 0 # Reserved
198 .word CODE_SEL # CS
199 .word 0 # Reserved
200 .word DATA_SEL # SS
201 .word 0 # Reserved
202 .word DATA_SEL # DS
203 .word 0 # Reserved
204 .word DATA_SEL # FS
205 .word 0 # Reserved
206 .word DATA_SEL # GS
207 .word 0 # Reserved
208 .word 0 # LDT Selector
209 .word 0 # Reserved
210 .word 0 # T
211 .word 0 # I/O Map Base
212
213 ASM_PFX(gcPsd):
214 .ascii "PSDSIG "
215 .word PSD_SIZE
216 .word 2
217 .word 1 << 2
218 .word CODE_SEL
219 .word DATA_SEL
220 .word DATA_SEL
221 .word DATA_SEL
222 .word 0
223 .long 0
224 .long 0
225 .long 0
226 .long 0
227 .quad 0
228 .long NullSeg
229 .long 0
230 .long GDT_SIZE
231 .long 0
232 .space 24, 0
233 .long ASM_PFX(gSmiMtrrs)
234 .long 0
235 .equ PSD_SIZE, . - ASM_PFX(gcPsd)
236
237 ASM_PFX(gcSmiGdtr): .word GDT_SIZE - 1
238 .long NullSeg
239
240 ASM_PFX(gcSmiIdtr): .word 0
241 .long 0
242
243 ASM_PFX(gTaskGateDescriptor):
244 .word 0 # Reserved
245 .word EXCEPTION_TSS_SEL # TSS Segment selector
246 .byte 0 # Reserved
247 .byte 0x85 # Task Gate, present, DPL = 0
248 .word 0 # Reserved
249
250 .text
251
252 #------------------------------------------------------------------------------
253 # PageFaultIdtHandlerSmmProfile is the entry point for all exceptions
254 #
255 # Stack:
256 #+---------------------+
257 #+ EFlags +
258 #+---------------------+
259 #+ CS +
260 #+---------------------+
261 #+ EIP +
262 #+---------------------+
263 #+ Error Code +
264 #+---------------------+
265 #+ Vector Number +
266 #+---------------------+
267 #+ EBP +
268 #+---------------------+ <-- EBP
269 #
270 # RSP set to odd multiple of 8 means ErrCode PRESENT
271 #------------------------------------------------------------------------------
272 ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
273 ASM_PFX(PageFaultIdtHandlerSmmProfile):
274 pushl $0x0e # Page Fault
275 pushl %ebp
276 movl %esp, %ebp
277
278
279 #
280 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
281 # is 16-byte aligned
282 #
283 andl $0xfffffff0, %esp
284 subl $12, %esp
285
286 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
287 pushl %eax
288 pushl %ecx
289 pushl %edx
290 pushl %ebx
291 leal (6*4)(%ebp), %ecx
292 pushl %ecx # ESP
293 pushl (%ebp) # EBP
294 pushl %esi
295 pushl %edi
296
297 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
298 movl %ss, %eax
299 pushl %eax
300 movzwl (4*4)(%ebp), %eax
301 pushl %eax
302 movl %ds, %eax
303 pushl %eax
304 movl %es, %eax
305 pushl %eax
306 movl %fs, %eax
307 pushl %eax
308 movl %gs, %eax
309 pushl %eax
310
311 ## UINT32 Eip;
312 movl (3*4)(%ebp), %eax
313 pushl %eax
314
315 ## UINT32 Gdtr[2], Idtr[2];
316 subl $8, %esp
317 sidt (%esp)
318 movl 2(%esp), %eax
319 xchgl (%esp), %eax
320 andl $0xffff, %eax
321 movl %eax, 4(%esp)
322
323 subl $8, %esp
324 sgdt (%esp)
325 movl 2(%esp), %eax
326 xchgl (%esp), %eax
327 andl $0xffff, %eax
328 movl %eax, 4(%esp)
329
330 ## UINT32 Ldtr, Tr;
331 xorl %eax, %eax
332 strw %ax
333 pushl %eax
334 sldtw %ax
335 pushl %eax
336
337 ## UINT32 EFlags;
338 movl (5*4)(%ebp), %eax
339 pushl %eax
340
341 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
342 movl %cr4, %eax
343 orl $0x208, %eax
344 movl %eax, %cr4
345 pushl %eax
346 movl %cr3, %eax
347 pushl %eax
348 movl %cr2, %eax
349 pushl %eax
350 xorl %eax, %eax
351 pushl %eax
352 movl %cr0, %eax
353 pushl %eax
354
355 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
356 movl %dr7, %eax
357 pushl %eax
358 movl %dr6, %eax
359 pushl %eax
360 movl %dr3, %eax
361 pushl %eax
362 movl %dr2, %eax
363 pushl %eax
364 movl %dr1, %eax
365 pushl %eax
366 movl %dr0, %eax
367 pushl %eax
368
369 ## FX_SAVE_STATE_IA32 FxSaveState;
370 subl $512, %esp
371 movl %esp, %edi
372 .byte 0x0f, 0xae, 0x07 #fxsave [edi]
373
374 # UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
375 cld
376
377 ## UINT32 ExceptionData;
378 pushl (2*4)(%ebp)
379
380 ## call into exception handler
381
382 ## Prepare parameter and call
383 movl %esp, %edx
384 pushl %edx
385 movl (1*4)(%ebp), %edx
386 pushl %edx
387
388 #
389 # Call External Exception Handler
390 #
391 movl $ASM_PFX(SmiPFHandler), %eax
392 call *%eax
393 addl $8, %esp
394 jmp L4
395
396 L4:
397 ## UINT32 ExceptionData;
398 addl $4, %esp
399
400 ## FX_SAVE_STATE_IA32 FxSaveState;
401 movl %esp, %esi
402 .byte 0xf, 0xae, 0xe # fxrstor [esi]
403 addl $512, %esp
404
405 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
406 ## Skip restoration of DRx registers to support debuggers
407 ## that set breakpoints in interrupt/exception context
408 addl $4*6, %esp
409
410 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
411 popl %eax
412 movl %eax, %cr0
413 addl $4, %esp # not for Cr1
414 popl %eax
415 movl %eax, %cr2
416 popl %eax
417 movl %eax, %cr3
418 popl %eax
419 movl %eax, %cr4
420
421 ## UINT32 EFlags;
422 popl (5*4)(%ebp)
423
424 ## UINT32 Ldtr, Tr;
425 ## UINT32 Gdtr[2], Idtr[2];
426 ## Best not let anyone mess with these particular registers...
427 addl $24, %esp
428
429 ## UINT32 Eip;
430 popl (3*4)(%ebp)
431
432 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
433 ## NOTE - modified segment registers could hang the debugger... We
434 ## could attempt to insulate ourselves against this possibility,
435 ## but that poses risks as well.
436 ##
437 popl %gs
438 popl %fs
439 popl %es
440 popl %ds
441 popl (4*4)(%ebp)
442 popl %ss
443
444 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
445 popl %edi
446 popl %esi
447 addl $4, %esp # not for ebp
448 addl $4, %esp # not for esp
449 popl %ebx
450 popl %edx
451 popl %ecx
452 popl %eax
453
454 movl %ebp, %esp
455 popl %ebp
456
457 # Enable TF bit after page fault handler runs
458 btsl $8, 16(%esp) # EFLAGS
459
460 addl $8, %esp # skip INT# & ErrCode
461 Return:
462 iret
463 #
464 # Page Fault Exception Handler entry when SMM Stack Guard is enabled
465 # Executiot starts here after a task switch
466 #
467 PFHandlerEntry:
468 #
469 # Get this processor's TSS
470 #
471 subl $8, %esp
472 sgdt 2(%esp)
473 movl 4(%esp), %eax # GDT base
474 addl $8, %esp
475 movl (TSS_SEL+2)(%eax), %ecx
476 shll $8, %ecx
477 movb (TSS_SEL+7)(%eax), %cl
478 rorl $8, %ecx # ecx = TSS base
479
480 movl %esp, %ebp
481
482 #
483 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
484 # is 16-byte aligned
485 #
486 andl $0xfffffff0, %esp
487 subl $12, %esp
488
489 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
490 pushl TSS_EAX(%ecx)
491 pushl TSS_ECX(%ecx)
492 pushl TSS_EDX(%ecx)
493 pushl TSS_EBX(%ecx)
494 pushl TSS_ESP(%ecx)
495 pushl TSS_EBP(%ecx)
496 pushl TSS_ESI(%ecx)
497 pushl TSS_EDI(%ecx)
498
499 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
500 movzwl TSS_SS(%ecx), %eax
501 pushl %eax
502 movzwl TSS_CS(%ecx), %eax
503 pushl %eax
504 movzwl TSS_DS(%ecx), %eax
505 pushl %eax
506 movzwl TSS_ES(%ecx), %eax
507 pushl %eax
508 movzwl TSS_FS(%ecx), %eax
509 pushl %eax
510 movzwl TSS_GS(%ecx), %eax
511 pushl %eax
512
513 ## UINT32 Eip;
514 pushl TSS_EIP(%ecx)
515
516 ## UINT32 Gdtr[2], Idtr[2];
517 subl $8, %esp
518 sidt (%esp)
519 movl 2(%esp), %eax
520 xchgl (%esp), %eax
521 andl $0xFFFF, %eax
522 movl %eax, 4(%esp)
523
524 subl $8, %esp
525 sgdt (%esp)
526 movl 2(%esp), %eax
527 xchgl (%esp), %eax
528 andl $0xFFFF, %eax
529 movl %eax, 4(%esp)
530
531 ## UINT32 Ldtr, Tr;
532 movl $TSS_SEL, %eax
533 pushl %eax
534 movzwl TSS_LDT(%ecx), %eax
535 pushl %eax
536
537 ## UINT32 EFlags;
538 pushl TSS_EFLAGS(%ecx)
539
540 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
541 movl %cr4, %eax
542 orl $0x208, %eax
543 movl %eax, %cr4
544 pushl %eax
545 movl %cr3, %eax
546 pushl %eax
547 movl %cr2, %eax
548 pushl %eax
549 xorl %eax, %eax
550 pushl %eax
551 movl %cr0, %eax
552 pushl %eax
553
554 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
555 movl %dr7, %eax
556 pushl %eax
557 movl %dr6, %eax
558 pushl %eax
559 movl %dr3, %eax
560 pushl %eax
561 movl %dr2, %eax
562 pushl %eax
563 movl %dr1, %eax
564 pushl %eax
565 movl %dr0, %eax
566 pushl %eax
567
568 ## FX_SAVE_STATE_IA32 FxSaveState;
569 ## Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
570 ## when executing fxsave/fxrstor instruction
571 clts
572 subl $512, %esp
573 movl %esp, %edi
574 .byte 0x0f, 0xae, 0x07 #fxsave [edi]
575
576 # UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
577 cld
578
579 ## UINT32 ExceptionData;
580 pushl (%ebp)
581
582 ## call into exception handler
583 movl %ecx, %ebx
584 movl $ASM_PFX(SmiPFHandler), %eax
585
586 ## Prepare parameter and call
587 movl %esp, %edx
588 pushl %edx
589 movl $14, %edx
590 pushl %edx
591
592 #
593 # Call External Exception Handler
594 #
595 call *%eax
596 addl $8, %esp
597
598 movl %ebx, %ecx
599 ## UINT32 ExceptionData;
600 addl $4, %esp
601
602 ## FX_SAVE_STATE_IA32 FxSaveState;
603 movl %esp, %esi
604 .byte 0xf, 0xae, 0xe # fxrstor [esi]
605 addl $512, %esp
606
607 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
608 ## Skip restoration of DRx registers to support debuggers
609 ## that set breakpoints in interrupt/exception context
610 addl $4*6, %esp
611
612 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
613 popl %eax
614 movl %eax, %cr0
615 addl $4, %esp # not for Cr1
616 popl %eax
617 movl %eax, %cr2
618 popl %eax
619 movl %eax, TSS_CR3(%ecx)
620 popl %eax
621 movl %eax, %cr4
622
623 ## UINT32 EFlags;
624 popl TSS_EFLAGS(%ecx)
625
626 ## UINT32 Ldtr, Tr;
627 ## UINT32 Gdtr[2], Idtr[2];
628 ## Best not let anyone mess with these particular registers...
629 addl $24, %esp
630
631 ## UINT32 Eip;
632 popl TSS_EIP(%ecx)
633
634 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
635 ## NOTE - modified segment registers could hang the debugger... We
636 ## could attempt to insulate ourselves against this possibility,
637 ## but that poses risks as well.
638 ##
639 popl %eax
640 movw %ax, TSS_GS(%ecx)
641 popl %eax
642 movw %ax, TSS_FS(%ecx)
643 popl %eax
644 movw %ax, TSS_ES(%ecx)
645 popl %eax
646 movw %ax, TSS_DS(%ecx)
647 popl %eax
648 movw %ax, TSS_CS(%ecx)
649 popl %eax
650 movw %ax, TSS_SS(%ecx)
651
652 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
653 popl TSS_EDI(%ecx)
654 popl TSS_ESI(%ecx)
655 addl $4, %esp # not for ebp
656 addl $4, %esp # not for esp
657 popl TSS_EBX(%ecx)
658 popl TSS_EDX(%ecx)
659 popl TSS_ECX(%ecx)
660 popl TSS_EAX(%ecx)
661
662 movl %ebp, %esp
663
664 # Set single step DB# if SMM profile is enabled and page fault exception happens
665 cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
666 jz Done2
667 # Create return context for iret in stub function
668 movl TSS_ESP(%ecx), %eax # Get old stack pointer
669 movl TSS_EIP(%ecx), %ebx
670 movl %ebx, -0xc(%eax) # create EIP in old stack
671 movzwl TSS_CS(%ecx), %ebx
672 movl %ebx, -0x8(%eax) # create CS in old stack
673 movl TSS_EFLAGS(%ecx), %ebx
674 btsl $8,%ebx
675 movl %ebx, -0x4(%eax) # create eflags in old stack
676 movl TSS_ESP(%ecx), %eax # Get old stack pointer
677 subl $12, %eax # minus 12 byte
678 movl %eax, TSS_ESP(%ecx) # Set new stack pointer
679
680 # Replace the EIP of interrupted task with stub function
681 movl $ASM_PFX(PageFaultStubFunction), %eax
682 movl %eax, TSS_EIP(%ecx)
683 # Jump to the iret so next page fault handler as a task will start again after iret.
684
685 Done2:
686
687 addl $4, %esp # skip ErrCode
688
689 jmp Return
690
691 ASM_PFX(PageFaultStubFunction):
692 #
693 # we need clean TS bit in CR0 to execute
694 # x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
695 #
696 clts
697 iret