--- /dev/null
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+# Module Name:\r
+#\r
+# SmiException.S\r
+#\r
+# Abstract:\r
+#\r
+# Exception handlers used in SM mode\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+ASM_GLOBAL ASM_PFX(SmiPFHandler)\r
+ASM_GLOBAL ASM_PFX(gSmiMtrrs)\r
+ASM_GLOBAL ASM_PFX(gcSmiIdtr)\r
+ASM_GLOBAL ASM_PFX(gcSmiGdtr)\r
+ASM_GLOBAL ASM_PFX(gcPsd)\r
+\r
+ .data\r
+\r
+NullSeg: .quad 0 # reserved by architecture\r
+CodeSeg32:\r
+ .word -1 # LimitLow\r
+ .word 0 # BaseLow\r
+ .byte 0 # BaseMid\r
+ .byte 0x9b\r
+ .byte 0xcf # LimitHigh\r
+ .byte 0 # BaseHigh\r
+ProtModeCodeSeg32:\r
+ .word -1 # LimitLow\r
+ .word 0 # BaseLow\r
+ .byte 0 # BaseMid\r
+ .byte 0x9b\r
+ .byte 0xcf # LimitHigh\r
+ .byte 0 # BaseHigh\r
+ProtModeSsSeg32:\r
+ .word -1 # LimitLow\r
+ .word 0 # BaseLow\r
+ .byte 0 # BaseMid\r
+ .byte 0x93\r
+ .byte 0xcf # LimitHigh\r
+ .byte 0 # BaseHigh\r
+DataSeg32:\r
+ .word -1 # LimitLow\r
+ .word 0 # BaseLow\r
+ .byte 0 # BaseMid\r
+ .byte 0x93\r
+ .byte 0xcf # LimitHigh\r
+ .byte 0 # BaseHigh\r
+CodeSeg16:\r
+ .word -1\r
+ .word 0\r
+ .byte 0\r
+ .byte 0x9b\r
+ .byte 0x8f\r
+ .byte 0\r
+DataSeg16:\r
+ .word -1\r
+ .word 0\r
+ .byte 0\r
+ .byte 0x93\r
+ .byte 0x8f\r
+ .byte 0\r
+CodeSeg64:\r
+ .word -1 # LimitLow\r
+ .word 0 # BaseLow\r
+ .byte 0 # BaseMid\r
+ .byte 0x9b\r
+ .byte 0xaf # LimitHigh\r
+ .byte 0 # BaseHigh\r
+# TSS Segment for X64 specially\r
+TssSeg:\r
+ .word TSS_DESC_SIZE # LimitLow\r
+ .word 0 # BaseLow\r
+ .byte 0 # BaseMid\r
+ .byte 0x89\r
+ .byte 0xDB # LimitHigh\r
+ .byte 0 # BaseHigh\r
+ .long 0 # BaseUpper\r
+ .long 0 # Reserved\r
+.equ GDT_SIZE, .- NullSeg\r
+\r
+TssDescriptor:\r
+ .space 104, 0\r
+.equ TSS_DESC_SIZE, .- TssDescriptor\r
+\r
+#\r
+# This structure serves as a template for all processors.\r
+#\r
+ASM_PFX(gcPsd):\r
+ .ascii "PSDSIG "\r
+ .word PSD_SIZE\r
+ .word 2\r
+ .word 1 << 2\r
+ .word CODE_SEL\r
+ .word DATA_SEL\r
+ .word DATA_SEL\r
+ .word DATA_SEL\r
+ .word 0\r
+ .quad 0\r
+ .quad 0\r
+ .quad 0 # fixed in InitializeMpServiceData()\r
+ .quad NullSeg\r
+ .long GDT_SIZE\r
+ .long 0\r
+ .space 24, 0\r
+ .quad ASM_PFX(gSmiMtrrs)\r
+.equ PSD_SIZE, . - ASM_PFX(gcPsd)\r
+\r
+#\r
+# CODE & DATA segments for SMM runtime\r
+#\r
+.equ CODE_SEL, CodeSeg64 - NullSeg\r
+.equ DATA_SEL, DataSeg32 - NullSeg\r
+.equ CODE32_SEL, CodeSeg32 - NullSeg\r
+\r
+ASM_PFX(gcSmiGdtr):\r
+ .word GDT_SIZE - 1\r
+ .quad NullSeg\r
+\r
+ASM_PFX(gcSmiIdtr):\r
+ .word IDT_SIZE - 1\r
+ .quad _SmiIDT\r
+\r
+\r
+#\r
+# Here is the IDT. There are 32 (not 255) entries in it since only processor\r
+# generated exceptions will be handled.\r
+#\r
+_SmiIDT:\r
+# The following segment repeats 32 times:\r
+# No. 1\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 2\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 3\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 4\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 5\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 6\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 7\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 8\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 9\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 10\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 11\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 12\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 13\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 14\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 15\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 16\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 17\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 18\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 19\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 20\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 21\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 22\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 23\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 24\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 25\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 26\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 27\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 28\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 29\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 30\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 31\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+# No. 32\r
+ .word 0 # Offset 0:15\r
+ .word CODE_SEL\r
+ .byte 0 # Unused\r
+ .byte 0x8e # Interrupt Gate, Present\r
+ .word 0 # Offset 16:31\r
+ .quad 0 # Offset 32:63\r
+\r
+_SmiIDTEnd:\r
+\r
+.equ IDT_SIZE, (_SmiIDTEnd - _SmiIDT)\r
+\r
+ .text\r
+\r
+#------------------------------------------------------------------------------\r
+# _SmiExceptionEntryPoints is the collection of exception entry points followed\r
+# by a common exception handler.\r
+#\r
+# Stack frame would be as follows as specified in IA32 manuals:\r
+# +---------------------+ <-- 16-byte aligned ensured by processor\r
+# + Old SS +\r
+# +---------------------+\r
+# + Old RSP +\r
+# +---------------------+\r
+# + RFlags +\r
+# +---------------------+\r
+# + CS +\r
+# +---------------------+\r
+# + RIP +\r
+# +---------------------+\r
+# + Error Code +\r
+# +---------------------+\r
+# + Vector Number +\r
+# +---------------------+\r
+# + RBP +\r
+# +---------------------+ <-- RBP, 16-byte aligned\r
+#\r
+# RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT\r
+#------------------------------------------------------------------------------\r
+ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)\r
+ASM_PFX(PageFaultIdtHandlerSmmProfile):\r
+ pushq $0x0e # Page Fault\r
+ .byte 0x40, 0xf6, 0xc4, 0x08 #test spl, 8\r
+ jnz L1\r
+ pushq (%rsp)\r
+ movq $0, 8(%rsp)\r
+L1:\r
+ pushq %rbp\r
+ movq %rsp, %rbp\r
+\r
+ #\r
+ # Since here the stack pointer is 16-byte aligned, so\r
+ # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
+ # is 16-byte aligned\r
+ #\r
+\r
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ pushq %r15\r
+ pushq %r14\r
+ pushq %r13\r
+ pushq %r12\r
+ pushq %r11\r
+ pushq %r10\r
+ pushq %r9\r
+ pushq %r8\r
+ pushq %rax\r
+ pushq %rcx\r
+ pushq %rdx\r
+ pushq %rbx\r
+ pushq 48(%rbp) # RSP\r
+ pushq (%rbp) # RBP\r
+ pushq %rsi\r
+ pushq %rdi\r
+\r
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
+ movzwq 56(%rbp), %rax\r
+ pushq %rax # for ss\r
+ movzwq 32(%rbp), %rax\r
+ pushq %rax # for cs\r
+ movq %ds, %rax\r
+ pushq %rax\r
+ movq %es, %rax\r
+ pushq %rax\r
+ movq %fs, %rax\r
+ pushq %rax\r
+ movq %gs, %rax\r
+ pushq %rax\r
+\r
+## UINT64 Rip;\r
+ pushq 24(%rbp)\r
+\r
+## UINT64 Gdtr[2], Idtr[2];\r
+ subq $16, %rsp\r
+ sidt (%rsp)\r
+ subq $16, %rsp\r
+ sgdt (%rsp)\r
+\r
+## UINT64 Ldtr, Tr;\r
+ xorq %rax, %rax\r
+ strw %ax\r
+ pushq %rax\r
+ sldtw %ax\r
+ pushq %rax\r
+\r
+## UINT64 RFlags;\r
+ pushq 40(%rbp)\r
+\r
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ movq %cr8, %rax\r
+ pushq %rax\r
+ movq %cr4, %rax\r
+ orq $0x208, %rax\r
+ movq %rax, %cr4\r
+ pushq %rax\r
+ movq %cr3, %rax\r
+ pushq %rax\r
+ movq %cr2, %rax\r
+ pushq %rax\r
+ xorq %rax, %rax\r
+ pushq %rax\r
+ movq %cr0, %rax\r
+ pushq %rax\r
+\r
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ movq %dr7, %rax\r
+ pushq %rax\r
+ movq %dr6, %rax\r
+ pushq %rax\r
+ movq %dr3, %rax\r
+ pushq %rax\r
+ movq %dr2, %rax\r
+ pushq %rax\r
+ movq %dr1, %rax\r
+ pushq %rax\r
+ movq %dr0, %rax\r
+ pushq %rax\r
+\r
+## FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+ subq $512, %rsp\r
+ movq %rsp, %rdi\r
+ .byte 0xf, 0xae, 0x7 # fxsave [rdi]\r
+\r
+# UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
+ cld\r
+\r
+## UINT32 ExceptionData;\r
+ pushq 16(%rbp)\r
+\r
+## call into exception handler\r
+ movq 8(%rbp), %rcx\r
+ movabsq $ASM_PFX(SmiPFHandler), %rax\r
+\r
+## Prepare parameter and call\r
+ movq %rsp, %rdx\r
+ #\r
+ # Per X64 calling convention, allocate maximum parameter stack space\r
+ # and make sure RSP is 16-byte aligned\r
+ #\r
+ subq $4 * 8 + 8, %rsp\r
+ call *%rax\r
+ addq $4 * 8 + 8, %rsp\r
+ jmp L5\r
+\r
+L5:\r
+## UINT64 ExceptionData;\r
+ addq $8, %rsp\r
+\r
+## FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+ movq %rsp, %rsi\r
+ .byte 0xf, 0xae, 0xe # fxrstor [rsi]\r
+ addq $512, %rsp\r
+\r
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+## Skip restoration of DRx registers to support debuggers\r
+## that set breakpoints in interrupt/exception context\r
+ addq $8 * 6, %rsp\r
+\r
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ popq %rax\r
+ movq %rax, %cr0\r
+ addq $8, %rsp # not for Cr1\r
+ popq %rax\r
+ movq %rax, %cr2\r
+ popq %rax\r
+ movq %rax, %cr3\r
+ popq %rax\r
+ movq %rax, %cr4\r
+ popq %rax\r
+ movq %rax, %cr8\r
+\r
+## UINT64 RFlags;\r
+ popq 40(%rbp)\r
+\r
+## UINT64 Ldtr, Tr;\r
+## UINT64 Gdtr[2], Idtr[2];\r
+## Best not let anyone mess with these particular registers...\r
+ addq $48, %rsp\r
+\r
+## UINT64 Rip;\r
+ popq 24(%rbp)\r
+\r
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+ popq %rax\r
+ # mov gs, rax ; not for gs\r
+ popq %rax\r
+ # mov fs, rax ; not for fs\r
+ # (X64 will not use fs and gs, so we do not restore it)\r
+ popq %rax\r
+ movq %rax, %es\r
+ popq %rax\r
+ movq %rax, %ds\r
+ popq 32(%rbp) # for cs\r
+ popq 56(%rbp) # for ss\r
+\r
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ popq %rdi\r
+ popq %rsi\r
+ addq $8, %rsp # not for rbp\r
+ popq 48(%rbp) # for rsp\r
+ popq %rbx\r
+ popq %rdx\r
+ popq %rcx\r
+ popq %rax\r
+ popq %r8\r
+ popq %r9\r
+ popq %r10\r
+ popq %r11\r
+ popq %r12\r
+ popq %r13\r
+ popq %r14\r
+ popq %r15\r
+\r
+ movq %rbp, %rsp\r
+\r
+# Enable TF bit after page fault handler runs\r
+ btsl $8, 40(%rsp) #RFLAGS\r
+\r
+ popq %rbp\r
+ addq $16, %rsp # skip INT# & ErrCode\r
+ iretq\r
+\r
+ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard)\r
+ASM_PFX(InitializeIDTSmmStackGuard):\r
+# If SMM Stack Guard feature is enabled, set the IST field of\r
+# the interrupt gate for Page Fault Exception to be 1\r
+#\r
+ movabsq $_SmiIDT + 14 * 16, %rax\r
+ movb $1, 4(%rax)\r
+ ret\r