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(gSmiMtrrs) 24ASM_GLOBAL ASM_PFX(gcSmiIdtr) 25ASM_GLOBAL ASM_PFX(gcSmiGdtr) 26ASM_GLOBAL ASM_PFX(gcPsd) 27 28 .data 29 30NullSeg: .quad 0 # reserved by architecture 31CodeSeg32: 32 .word -1 # LimitLow 33 .word 0 # BaseLow 34 .byte 0 # BaseMid 35 .byte 0x9b 36 .byte 0xcf # LimitHigh 37 .byte 0 # BaseHigh 38ProtModeCodeSeg32: 39 .word -1 # LimitLow 40 .word 0 # BaseLow 41 .byte 0 # BaseMid 42 .byte 0x9b 43 .byte 0xcf # LimitHigh 44 .byte 0 # BaseHigh 45ProtModeSsSeg32: 46 .word -1 # LimitLow 47 .word 0 # BaseLow 48 .byte 0 # BaseMid 49 .byte 0x93 50 .byte 0xcf # LimitHigh 51 .byte 0 # BaseHigh 52DataSeg32: 53 .word -1 # LimitLow 54 .word 0 # BaseLow 55 .byte 0 # BaseMid 56 .byte 0x93 57 .byte 0xcf # LimitHigh 58 .byte 0 # BaseHigh 59CodeSeg16: 60 .word -1 61 .word 0 62 .byte 0 63 .byte 0x9b 64 .byte 0x8f 65 .byte 0 66DataSeg16: 67 .word -1 68 .word 0 69 .byte 0 70 .byte 0x93 71 .byte 0x8f 72 .byte 0 73CodeSeg64: 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 81TssSeg: 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 92TssDescriptor: 93 .space 104, 0 94.equ TSS_DESC_SIZE, .- TssDescriptor 95 96# 97# This structure serves as a template for all processors. 98# 99ASM_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 126ASM_PFX(gcSmiGdtr): 127 .word GDT_SIZE - 1 128 .quad NullSeg 129 130ASM_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#------------------------------------------------------------------------------ 397ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile) 398ASM_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) 404L1: 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 523L5: 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 603ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard) 604ASM_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