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 22ASM_GLOBAL ASM_PFX(SmiPFHandler) 23ASM_GLOBAL ASM_PFX(PageFaultStubFunction) 24ASM_GLOBAL ASM_PFX(gSmiMtrrs) 25ASM_GLOBAL ASM_PFX(gcSmiIdtr) 26ASM_GLOBAL ASM_PFX(gcSmiGdtr) 27ASM_GLOBAL ASM_PFX(gcPsd) 28ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable)) 29 30 .data 31 32NullSeg: .quad 0 # reserved by architecture 33CodeSeg32: 34 .word -1 # LimitLow 35 .word 0 # BaseLow 36 .byte 0 # BaseMid 37 .byte 0x9b 38 .byte 0xcf # LimitHigh 39 .byte 0 # BaseHigh 40ProtModeCodeSeg32: 41 .word -1 # LimitLow 42 .word 0 # BaseLow 43 .byte 0 # BaseMid 44 .byte 0x9b 45 .byte 0xcf # LimitHigh 46 .byte 0 # BaseHigh 47ProtModeSsSeg32: 48 .word -1 # LimitLow 49 .word 0 # BaseLow 50 .byte 0 # BaseMid 51 .byte 0x93 52 .byte 0xcf # LimitHigh 53 .byte 0 # BaseHigh 54DataSeg32: 55 .word -1 # LimitLow 56 .word 0 # BaseLow 57 .byte 0 # BaseMid 58 .byte 0x93 59 .byte 0xcf # LimitHigh 60 .byte 0 # BaseHigh 61CodeSeg16: 62 .word -1 63 .word 0 64 .byte 0 65 .byte 0x9b 66 .byte 0x8f 67 .byte 0 68DataSeg16: 69 .word -1 70 .word 0 71 .byte 0 72 .byte 0x93 73 .byte 0x8f 74 .byte 0 75CodeSeg64: 76 .word -1 # LimitLow 77 .word 0 # BaseLow 78 .byte 0 # BaseMid 79 .byte 0x9b 80 .byte 0xaf # LimitHigh 81 .byte 0 # BaseHigh 82.equ GDT_SIZE, .- NullSeg 83 84TssSeg: 85 .word TSS_DESC_SIZE -1 # LimitLow 86 .word 0 # BaseLow 87 .byte 0 # BaseMid 88 .byte 0x89 89 .byte 0x00 # LimitHigh 90 .byte 0 # BaseHigh 91ExceptionTssSeg: 92 .word TSS_DESC_SIZE - 1 # LimitLow 93 .word 0 # BaseLow 94 .byte 0 # BaseMid 95 .byte 0x89 96 .byte 0x00 # LimitHigh 97 .byte 0 # BaseHigh 98 99.equ CODE_SEL, CodeSeg32 - NullSeg 100.equ DATA_SEL, DataSeg32 - NullSeg 101.equ TSS_SEL, TssSeg - NullSeg 102.equ EXCEPTION_TSS_SEL, ExceptionTssSeg - NullSeg 103 104# IA32 TSS fields 105.equ TSS_ESP0, 4 106.equ TSS_SS0, 8 107.equ TSS_ESP1, 12 108.equ TSS_SS1, 16 109.equ TSS_ESP2, 20 110.equ TSS_SS2, 24 111.equ TSS_CR3, 28 112.equ TSS_EIP, 32 113.equ TSS_EFLAGS, 36 114.equ TSS_EAX, 40 115.equ TSS_ECX, 44 116.equ TSS_EDX, 48 117.equ TSS_EBX, 52 118.equ TSS_ESP, 56 119.equ TSS_EBP, 60 120.equ TSS_ESI, 64 121.equ TSS_EDI, 68 122.equ TSS_ES, 72 123.equ TSS_CS, 76 124.equ TSS_SS, 80 125.equ TSS_DS, 84 126.equ TSS_FS, 88 127.equ TSS_GS, 92 128.equ TSS_LDT, 96 129 130# Create 2 TSS segments just after GDT 131TssDescriptor: 132 .word 0 # PreviousTaskLink 133 .word 0 # Reserved 134 .long 0 # ESP0 135 .word 0 # SS0 136 .word 0 # Reserved 137 .long 0 # ESP1 138 .word 0 # SS1 139 .word 0 # Reserved 140 .long 0 # ESP2 141 .word 0 # SS2 142 .word 0 # Reserved 143 .long 0 # CR3 144 .long 0 # EIP 145 .long 0 # EFLAGS 146 .long 0 # EAX 147 .long 0 # ECX 148 .long 0 # EDX 149 .long 0 # EBX 150 .long 0 # ESP 151 .long 0 # EBP 152 .long 0 # ESI 153 .long 0 # EDI 154 .word 0 # ES 155 .word 0 # Reserved 156 .word 0 # CS 157 .word 0 # Reserved 158 .word 0 # SS 159 .word 0 # Reserved 160 .word 0 # DS 161 .word 0 # Reserved 162 .word 0 # FS 163 .word 0 # Reserved 164 .word 0 # GS 165 .word 0 # Reserved 166 .word 0 # LDT Selector 167 .word 0 # Reserved 168 .word 0 # T 169 .word 0 # I/O Map Base 170.equ TSS_DESC_SIZE, . - TssDescriptor 171 172ExceptionTssDescriptor: 173 .word 0 # PreviousTaskLink 174 .word 0 # Reserved 175 .long 0 # ESP0 176 .word 0 # SS0 177 .word 0 # Reserved 178 .long 0 # ESP1 179 .word 0 # SS1 180 .word 0 # Reserved 181 .long 0 # ESP2 182 .word 0 # SS2 183 .word 0 # Reserved 184 .long 0 # CR3 185 .long PFHandlerEntry # EIP 186 .long 00000002 # EFLAGS 187 .long 0 # EAX 188 .long 0 # ECX 189 .long 0 # EDX 190 .long 0 # EBX 191 .long 0 # ESP 192 .long 0 # EBP 193 .long 0 # ESI 194 .long 0 # EDI 195 .word DATA_SEL # ES 196 .word 0 # Reserved 197 .word CODE_SEL # CS 198 .word 0 # Reserved 199 .word DATA_SEL # SS 200 .word 0 # Reserved 201 .word DATA_SEL # DS 202 .word 0 # Reserved 203 .word DATA_SEL # FS 204 .word 0 # Reserved 205 .word DATA_SEL # GS 206 .word 0 # Reserved 207 .word 0 # LDT Selector 208 .word 0 # Reserved 209 .word 0 # T 210 .word 0 # I/O Map Base 211 212ASM_PFX(gcPsd): 213 .ascii "PSDSIG " 214 .word PSD_SIZE 215 .word 2 216 .word 1 << 2 217 .word CODE_SEL 218 .word DATA_SEL 219 .word DATA_SEL 220 .word DATA_SEL 221 .word 0 222 .long 0 223 .long 0 224 .long 0 225 .long 0 226 .quad 0 227 .long NullSeg 228 .long 0 229 .long GDT_SIZE 230 .long 0 231 .space 24, 0 232 .long ASM_PFX(gSmiMtrrs) 233 .long 0 234.equ PSD_SIZE, . - ASM_PFX(gcPsd) 235 236ASM_PFX(gcSmiGdtr): .word GDT_SIZE - 1 237 .long NullSeg 238 239ASM_PFX(gcSmiIdtr): .word IDT_SIZE - 1 240 .long _SmiIDT 241 242_SmiIDT: 243# The following segment repeats 32 times: 244# No. 1 245 .word 0 # Offset 0:15 246 .word CODE_SEL 247 .byte 0 # Unused 248 .byte 0x8e # Interrupt Gate, Present 249 .word 0 # Offset 16:31 250# No. 2 251 .word 0 # Offset 0:15 252 .word CODE_SEL 253 .byte 0 # Unused 254 .byte 0x8e # Interrupt Gate, Present 255 .word 0 # Offset 16:31 256# No. 3 257 .word 0 # Offset 0:15 258 .word CODE_SEL 259 .byte 0 # Unused 260 .byte 0x8e # Interrupt Gate, Present 261 .word 0 # Offset 16:31 262# No. 4 263 .word 0 # Offset 0:15 264 .word CODE_SEL 265 .byte 0 # Unused 266 .byte 0x8e # Interrupt Gate, Present 267 .word 0 # Offset 16:31 268# No. 5 269 .word 0 # Offset 0:15 270 .word CODE_SEL 271 .byte 0 # Unused 272 .byte 0x8e # Interrupt Gate, Present 273 .word 0 # Offset 16:31 274# No. 6 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# No. 7 281 .word 0 # Offset 0:15 282 .word CODE_SEL 283 .byte 0 # Unused 284 .byte 0x8e # Interrupt Gate, Present 285 .word 0 # Offset 16:31 286# No. 8 287 .word 0 # Offset 0:15 288 .word CODE_SEL 289 .byte 0 # Unused 290 .byte 0x8e # Interrupt Gate, Present 291 .word 0 # Offset 16:31 292# No. 9 293 .word 0 # Offset 0:15 294 .word CODE_SEL 295 .byte 0 # Unused 296 .byte 0x8e # Interrupt Gate, Present 297 .word 0 # Offset 16:31 298# No. 10 299 .word 0 # Offset 0:15 300 .word CODE_SEL 301 .byte 0 # Unused 302 .byte 0x8e # Interrupt Gate, Present 303 .word 0 # Offset 16:31 304# No. 11 305 .word 0 # Offset 0:15 306 .word CODE_SEL 307 .byte 0 # Unused 308 .byte 0x8e # Interrupt Gate, Present 309 .word 0 # Offset 16:31 310# No. 12 311 .word 0 # Offset 0:15 312 .word CODE_SEL 313 .byte 0 # Unused 314 .byte 0x8e # Interrupt Gate, Present 315 .word 0 # Offset 16:31 316# No. 13 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# No. 14 323 .word 0 # Offset 0:15 324 .word CODE_SEL 325 .byte 0 # Unused 326 .byte 0x8e # Interrupt Gate, Present 327 .word 0 # Offset 16:31 328# No. 15 329 .word 0 # Offset 0:15 330 .word CODE_SEL 331 .byte 0 # Unused 332 .byte 0x8e # Interrupt Gate, Present 333 .word 0 # Offset 16:31 334# No. 16 335 .word 0 # Offset 0:15 336 .word CODE_SEL 337 .byte 0 # Unused 338 .byte 0x8e # Interrupt Gate, Present 339 .word 0 # Offset 16:31 340# No. 17 341 .word 0 # Offset 0:15 342 .word CODE_SEL 343 .byte 0 # Unused 344 .byte 0x8e # Interrupt Gate, Present 345 .word 0 # Offset 16:31 346# No. 18 347 .word 0 # Offset 0:15 348 .word CODE_SEL 349 .byte 0 # Unused 350 .byte 0x8e # Interrupt Gate, Present 351 .word 0 # Offset 16:31 352# No. 19 353 .word 0 # Offset 0:15 354 .word CODE_SEL 355 .byte 0 # Unused 356 .byte 0x8e # Interrupt Gate, Present 357 .word 0 # Offset 16:31 358# No. 20 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# No. 21 365 .word 0 # Offset 0:15 366 .word CODE_SEL 367 .byte 0 # Unused 368 .byte 0x8e # Interrupt Gate, Present 369 .word 0 # Offset 16:31 370# No. 22 371 .word 0 # Offset 0:15 372 .word CODE_SEL 373 .byte 0 # Unused 374 .byte 0x8e # Interrupt Gate, Present 375 .word 0 # Offset 16:31 376# No. 23 377 .word 0 # Offset 0:15 378 .word CODE_SEL 379 .byte 0 # Unused 380 .byte 0x8e # Interrupt Gate, Present 381 .word 0 # Offset 16:31 382# No. 24 383 .word 0 # Offset 0:15 384 .word CODE_SEL 385 .byte 0 # Unused 386 .byte 0x8e # Interrupt Gate, Present 387 .word 0 # Offset 16:31 388# No. 25 389 .word 0 # Offset 0:15 390 .word CODE_SEL 391 .byte 0 # Unused 392 .byte 0x8e # Interrupt Gate, Present 393 .word 0 # Offset 16:31 394# No. 26 395 .word 0 # Offset 0:15 396 .word CODE_SEL 397 .byte 0 # Unused 398 .byte 0x8e # Interrupt Gate, Present 399 .word 0 # Offset 16:31 400# No. 27 401 .word 0 # Offset 0:15 402 .word CODE_SEL 403 .byte 0 # Unused 404 .byte 0x8e # Interrupt Gate, Present 405 .word 0 # Offset 16:31 406# No. 28 407 .word 0 # Offset 0:15 408 .word CODE_SEL 409 .byte 0 # Unused 410 .byte 0x8e # Interrupt Gate, Present 411 .word 0 # Offset 16:31 412# No. 29 413 .word 0 # Offset 0:15 414 .word CODE_SEL 415 .byte 0 # Unused 416 .byte 0x8e # Interrupt Gate, Present 417 .word 0 # Offset 16:31 418# No. 30 419 .word 0 # Offset 0:15 420 .word CODE_SEL 421 .byte 0 # Unused 422 .byte 0x8e # Interrupt Gate, Present 423 .word 0 # Offset 16:31 424# No. 31 425 .word 0 # Offset 0:15 426 .word CODE_SEL 427 .byte 0 # Unused 428 .byte 0x8e # Interrupt Gate, Present 429 .word 0 # Offset 16:31 430# No. 32 431 .word 0 # Offset 0:15 432 .word CODE_SEL 433 .byte 0 # Unused 434 .byte 0x8e # Interrupt Gate, Present 435 .word 0 # Offset 16:31 436 437.equ IDT_SIZE, . - _SmiIDT 438 439TaskGateDescriptor: 440 .word 0 # Reserved 441 .word EXCEPTION_TSS_SEL # TSS Segment selector 442 .byte 0 # Reserved 443 .byte 0x85 # Task Gate, present, DPL = 0 444 .word 0 # Reserved 445 446 .text 447 448#------------------------------------------------------------------------------ 449# PageFaultIdtHandlerSmmProfile is the entry point for all exceptions 450# 451# Stack: 452#+---------------------+ 453#+ EFlags + 454#+---------------------+ 455#+ CS + 456#+---------------------+ 457#+ EIP + 458#+---------------------+ 459#+ Error Code + 460#+---------------------+ 461#+ Vector Number + 462#+---------------------+ 463#+ EBP + 464#+---------------------+ <-- EBP 465# 466# RSP set to odd multiple of 8 means ErrCode PRESENT 467#------------------------------------------------------------------------------ 468ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile) 469ASM_PFX(PageFaultIdtHandlerSmmProfile): 470 pushl $0x0e # Page Fault 471 pushl %ebp 472 movl %esp, %ebp 473 474 475 # 476 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32 477 # is 16-byte aligned 478 # 479 andl $0xfffffff0, %esp 480 subl $12, %esp 481 482## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 483 pushl %eax 484 pushl %ecx 485 pushl %edx 486 pushl %ebx 487 leal (6*4)(%ebp), %ecx 488 pushl %ecx # ESP 489 pushl (%ebp) # EBP 490 pushl %esi 491 pushl %edi 492 493## UINT32 Gs, Fs, Es, Ds, Cs, Ss; 494 movl %ss, %eax 495 pushl %eax 496 movzwl (4*4)(%ebp), %eax 497 pushl %eax 498 movl %ds, %eax 499 pushl %eax 500 movl %es, %eax 501 pushl %eax 502 movl %fs, %eax 503 pushl %eax 504 movl %gs, %eax 505 pushl %eax 506 507## UINT32 Eip; 508 movl (3*4)(%ebp), %eax 509 pushl %eax 510 511## UINT32 Gdtr[2], Idtr[2]; 512 subl $8, %esp 513 sidt (%esp) 514 movl 2(%esp), %eax 515 xchgl (%esp), %eax 516 andl $0xffff, %eax 517 movl %eax, 4(%esp) 518 519 subl $8, %esp 520 sgdt (%esp) 521 movl 2(%esp), %eax 522 xchgl (%esp), %eax 523 andl $0xffff, %eax 524 movl %eax, 4(%esp) 525 526## UINT32 Ldtr, Tr; 527 xorl %eax, %eax 528 strw %ax 529 pushl %eax 530 sldtw %ax 531 pushl %eax 532 533## UINT32 EFlags; 534 movl (5*4)(%ebp), %eax 535 pushl %eax 536 537## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 538 movl %cr4, %eax 539 orl $0x208, %eax 540 movl %eax, %cr4 541 pushl %eax 542 movl %cr3, %eax 543 pushl %eax 544 movl %cr2, %eax 545 pushl %eax 546 xorl %eax, %eax 547 pushl %eax 548 movl %cr0, %eax 549 pushl %eax 550 551## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 552 movl %dr7, %eax 553 pushl %eax 554 movl %dr6, %eax 555 pushl %eax 556 movl %dr3, %eax 557 pushl %eax 558 movl %dr2, %eax 559 pushl %eax 560 movl %dr1, %eax 561 pushl %eax 562 movl %dr0, %eax 563 pushl %eax 564 565## FX_SAVE_STATE_IA32 FxSaveState; 566 subl $512, %esp 567 movl %esp, %edi 568 .byte 0x0f, 0xae, 0x07 #fxsave [edi] 569 570# UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear 571 cld 572 573## UINT32 ExceptionData; 574 pushl (2*4)(%ebp) 575 576## call into exception handler 577 578## Prepare parameter and call 579 movl %esp, %edx 580 pushl %edx 581 movl (1*4)(%ebp), %edx 582 pushl %edx 583 584 # 585 # Call External Exception Handler 586 # 587 movl $ASM_PFX(SmiPFHandler), %eax 588 call *%eax 589 addl $8, %esp 590 jmp L4 591 592L4: 593## UINT32 ExceptionData; 594 addl $4, %esp 595 596## FX_SAVE_STATE_IA32 FxSaveState; 597 movl %esp, %esi 598 .byte 0xf, 0xae, 0xe # fxrstor [esi] 599 addl $512, %esp 600 601## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 602## Skip restoration of DRx registers to support debuggers 603## that set breakpoints in interrupt/exception context 604 addl $4*6, %esp 605 606## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 607 popl %eax 608 movl %eax, %cr0 609 addl $4, %esp # not for Cr1 610 popl %eax 611 movl %eax, %cr2 612 popl %eax 613 movl %eax, %cr3 614 popl %eax 615 movl %eax, %cr4 616 617## UINT32 EFlags; 618 popl (5*4)(%ebp) 619 620## UINT32 Ldtr, Tr; 621## UINT32 Gdtr[2], Idtr[2]; 622## Best not let anyone mess with these particular registers... 623 addl $24, %esp 624 625## UINT32 Eip; 626 popl (3*4)(%ebp) 627 628## UINT32 Gs, Fs, Es, Ds, Cs, Ss; 629## NOTE - modified segment registers could hang the debugger... We 630## could attempt to insulate ourselves against this possibility, 631## but that poses risks as well. 632## 633 popl %gs 634 popl %fs 635 popl %es 636 popl %ds 637 popl (4*4)(%ebp) 638 popl %ss 639 640## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 641 popl %edi 642 popl %esi 643 addl $4, %esp # not for ebp 644 addl $4, %esp # not for esp 645 popl %ebx 646 popl %edx 647 popl %ecx 648 popl %eax 649 650 movl %ebp, %esp 651 popl %ebp 652 653# Enable TF bit after page fault handler runs 654 btsl $8, 16(%esp) # EFLAGS 655 656 addl $8, %esp # skip INT# & ErrCode 657Return: 658 iret 659# 660# Page Fault Exception Handler entry when SMM Stack Guard is enabled 661# Executiot starts here after a task switch 662# 663PFHandlerEntry: 664# 665# Get this processor's TSS 666# 667 subl $8, %esp 668 sgdt 2(%esp) 669 movl 4(%esp), %eax # GDT base 670 addl $8, %esp 671 movl (TSS_SEL+2)(%eax), %ecx 672 shll $8, %ecx 673 movb (TSS_SEL+7)(%eax), %cl 674 rorl $8, %ecx # ecx = TSS base 675 676 movl %esp, %ebp 677 678 # 679 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32 680 # is 16-byte aligned 681 # 682 andl $0xfffffff0, %esp 683 subl $12, %esp 684 685## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 686 pushl TSS_EAX(%ecx) 687 pushl TSS_ECX(%ecx) 688 pushl TSS_EDX(%ecx) 689 pushl TSS_EBX(%ecx) 690 pushl TSS_ESP(%ecx) 691 pushl TSS_EBP(%ecx) 692 pushl TSS_ESI(%ecx) 693 pushl TSS_EDI(%ecx) 694 695## UINT32 Gs, Fs, Es, Ds, Cs, Ss; 696 movzwl TSS_SS(%ecx), %eax 697 pushl %eax 698 movzwl TSS_CS(%ecx), %eax 699 pushl %eax 700 movzwl TSS_DS(%ecx), %eax 701 pushl %eax 702 movzwl TSS_ES(%ecx), %eax 703 pushl %eax 704 movzwl TSS_FS(%ecx), %eax 705 pushl %eax 706 movzwl TSS_GS(%ecx), %eax 707 pushl %eax 708 709## UINT32 Eip; 710 pushl TSS_EIP(%ecx) 711 712## UINT32 Gdtr[2], Idtr[2]; 713 subl $8, %esp 714 sidt (%esp) 715 movl 2(%esp), %eax 716 xchgl (%esp), %eax 717 andl $0xFFFF, %eax 718 movl %eax, 4(%esp) 719 720 subl $8, %esp 721 sgdt (%esp) 722 movl 2(%esp), %eax 723 xchgl (%esp), %eax 724 andl $0xFFFF, %eax 725 movl %eax, 4(%esp) 726 727## UINT32 Ldtr, Tr; 728 movl $TSS_SEL, %eax 729 pushl %eax 730 movzwl TSS_LDT(%ecx), %eax 731 pushl %eax 732 733## UINT32 EFlags; 734 pushl TSS_EFLAGS(%ecx) 735 736## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 737 movl %cr4, %eax 738 orl $0x208, %eax 739 movl %eax, %cr4 740 pushl %eax 741 movl %cr3, %eax 742 pushl %eax 743 movl %cr2, %eax 744 pushl %eax 745 xorl %eax, %eax 746 pushl %eax 747 movl %cr0, %eax 748 pushl %eax 749 750## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 751 movl %dr7, %eax 752 pushl %eax 753 movl %dr6, %eax 754 pushl %eax 755 movl %dr3, %eax 756 pushl %eax 757 movl %dr2, %eax 758 pushl %eax 759 movl %dr1, %eax 760 pushl %eax 761 movl %dr0, %eax 762 pushl %eax 763 764## FX_SAVE_STATE_IA32 FxSaveState; 765## Clear TS bit in CR0 to avoid Device Not Available Exception (#NM) 766## when executing fxsave/fxrstor instruction 767 clts 768 subl $512, %esp 769 movl %esp, %edi 770 .byte 0x0f, 0xae, 0x07 #fxsave [edi] 771 772# UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear 773 cld 774 775## UINT32 ExceptionData; 776 pushl (%ebp) 777 778## call into exception handler 779 movl %ecx, %ebx 780 movl $ASM_PFX(SmiPFHandler), %eax 781 782## Prepare parameter and call 783 movl %esp, %edx 784 pushl %edx 785 movl $14, %edx 786 pushl %edx 787 788 # 789 # Call External Exception Handler 790 # 791 call *%eax 792 addl $8, %esp 793 794 movl %ebx, %ecx 795## UINT32 ExceptionData; 796 addl $4, %esp 797 798## FX_SAVE_STATE_IA32 FxSaveState; 799 movl %esp, %esi 800 .byte 0xf, 0xae, 0xe # fxrstor [esi] 801 addl $512, %esp 802 803## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 804## Skip restoration of DRx registers to support debuggers 805## that set breakpoints in interrupt/exception context 806 addl $4*6, %esp 807 808## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 809 popl %eax 810 movl %eax, %cr0 811 addl $4, %esp # not for Cr1 812 popl %eax 813 movl %eax, %cr2 814 popl %eax 815 movl %eax, TSS_CR3(%ecx) 816 popl %eax 817 movl %eax, %cr4 818 819## UINT32 EFlags; 820 popl TSS_EFLAGS(%ecx) 821 822## UINT32 Ldtr, Tr; 823## UINT32 Gdtr[2], Idtr[2]; 824## Best not let anyone mess with these particular registers... 825 addl $24, %esp 826 827## UINT32 Eip; 828 popl TSS_EIP(%ecx) 829 830## UINT32 Gs, Fs, Es, Ds, Cs, Ss; 831## NOTE - modified segment registers could hang the debugger... We 832## could attempt to insulate ourselves against this possibility, 833## but that poses risks as well. 834## 835 popl %eax 836 movw %ax, TSS_GS(%ecx) 837 popl %eax 838 movw %ax, TSS_FS(%ecx) 839 popl %eax 840 movw %ax, TSS_ES(%ecx) 841 popl %eax 842 movw %ax, TSS_DS(%ecx) 843 popl %eax 844 movw %ax, TSS_CS(%ecx) 845 popl %eax 846 movw %ax, TSS_SS(%ecx) 847 848## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 849 popl TSS_EDI(%ecx) 850 popl TSS_ESI(%ecx) 851 addl $4, %esp # not for ebp 852 addl $4, %esp # not for esp 853 popl TSS_EBX(%ecx) 854 popl TSS_EDX(%ecx) 855 popl TSS_ECX(%ecx) 856 popl TSS_EAX(%ecx) 857 858 movl %ebp, %esp 859 860# Set single step DB# if SMM profile is enabled and page fault exception happens 861 cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable)) 862 jz Done2 863# Create return context for iret in stub function 864 movl TSS_ESP(%ecx), %eax # Get old stack pointer 865 movl TSS_EIP(%ecx), %ebx 866 movl %ebx, -0xc(%eax) # create EIP in old stack 867 movzwl TSS_CS(%ecx), %ebx 868 movl %ebx, -0x8(%eax) # create CS in old stack 869 movl TSS_EFLAGS(%ecx), %ebx 870 btsl $8,%ebx 871 movl %ebx, -0x4(%eax) # create eflags in old stack 872 movl TSS_ESP(%ecx), %eax # Get old stack pointer 873 subl $12, %eax # minus 12 byte 874 movl %eax, TSS_ESP(%ecx) # Set new stack pointer 875 876# Replace the EIP of interrupted task with stub function 877 movl $ASM_PFX(PageFaultStubFunction), %eax 878 movl %eax, TSS_EIP(%ecx) 879# Jump to the iret so next page fault handler as a task will start again after iret. 880 881Done2: 882 883 addl $4, %esp # skip ErrCode 884 885 jmp Return 886 887ASM_PFX(PageFaultStubFunction): 888# 889# we need clean TS bit in CR0 to execute 890# x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. 891# 892 clts 893 iret 894 895ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard) 896ASM_PFX(InitializeIDTSmmStackGuard): 897 pushl %ebx 898# 899# If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT 900# is a Task Gate Descriptor so that when a Page Fault Exception occurs, 901# the processors can use a known good stack in case stack ran out. 902# 903 leal _SmiIDT + 14 * 8, %ebx 904 leal TaskGateDescriptor, %edx 905 movl (%edx), %eax 906 movl %eax, (%ebx) 907 movl 4(%edx), %eax 908 movl %eax, 4(%ebx) 909 910 popl %ebx 911 ret 912