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 - 1 # LimitLow 83 .word 0 # BaseLow 84 .byte 0 # BaseMid 85 .byte 0x89 86 .byte 0x00 # 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 611