]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.S
UefiCpuPkg: Add PiSmmCpuDxeSmm module X64 files
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiEntry.S
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.S b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.S
new file mode 100644 (file)
index 0000000..8315593
--- /dev/null
@@ -0,0 +1,217 @@
+#------------------------------------------------------------------------------\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
+#   SmiEntry.S\r
+#\r
+# Abstract:\r
+#\r
+#   Code template of the SMI handler for a particular processor\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+ASM_GLOBAL  ASM_PFX(gcSmiHandlerTemplate)\r
+ASM_GLOBAL  ASM_PFX(gcSmiHandlerSize)\r
+ASM_GLOBAL  ASM_PFX(gSmiCr3)\r
+ASM_GLOBAL  ASM_PFX(gSmiStack)\r
+ASM_GLOBAL  ASM_PFX(gSmbase)\r
+ASM_GLOBAL  ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))\r
+ASM_GLOBAL  ASM_PFX(gSmiHandlerIdtr)\r
+\r
+#\r
+# Constants relating to PROCESSOR_SMM_DESCRIPTOR\r
+#\r
+.equ            DSC_OFFSET, 0xfb00\r
+.equ            DSC_GDTPTR, 0x30\r
+.equ            DSC_GDTSIZ, 0x38\r
+.equ            DSC_CS, 14\r
+.equ            DSC_DS, 16\r
+.equ            DSC_SS, 18\r
+.equ            DSC_OTHERSEG, 20\r
+#\r
+# Constants relating to CPU State Save Area\r
+#\r
+.equ            SSM_DR6,   0xffd0\r
+.equ            SSM_DR7,   0xffc8\r
+\r
+.equ            PROTECT_MODE_CS, 0x08\r
+.equ            PROTECT_MODE_DS, 0x20\r
+.equ            LONG_MODE_CS, 0x38\r
+.equ            TSS_SEGMENT, 0x40\r
+.equ            GDT_SIZE, 0x50\r
+\r
+    .text\r
+\r
+ASM_PFX(gcSmiHandlerTemplate):\r
+\r
+_SmiEntryPoint:\r
+    #\r
+    # The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-\r
+    # bit addressing mode. And that coincidence has been used in the following\r
+    # "64-bit like" 16-bit code. Be aware that once RDI is referenced as a\r
+    # base address register, it is actually BX that is referenced.\r
+    #\r
+    .byte 0xbb                          # mov bx, imm16\r
+    .word _GdtDesc - _SmiEntryPoint + 0x8000\r
+    #\r
+    # fix GDT descriptor\r
+    #\r
+    .byte 0x2e,0xa1                     # mov ax, cs:[offset16]\r
+    .word      DSC_OFFSET + DSC_GDTSIZ\r
+    .byte 0x48                          # dec ax\r
+    .byte 0x2e\r
+    movl    %eax, (%rdi)                # mov cs:[bx], ax\r
+    .byte 0x66,0x2e,0xa1                # mov eax, cs:[offset16]\r
+    .word      DSC_OFFSET + DSC_GDTPTR\r
+    .byte 0x2e\r
+    movw    %ax, 2(%rdi)\r
+    .byte 0x66,0x2e\r
+    lgdt    (%rdi)\r
+    #\r
+    # Patch ProtectedMode Segment\r
+    #\r
+    .byte 0xb8\r
+    .word PROTECT_MODE_CS\r
+    .byte 0x2e\r
+    movl    %eax, -2(%rdi)\r
+    #\r
+    # Patch ProtectedMode entry\r
+    #\r
+    .byte 0x66, 0xbf                    # mov edi, SMBASE\r
+ASM_PFX(gSmbase): .space 4\r
+    lea     ((ProtectedMode - _SmiEntryPoint) + 0x8000)(%edi), %ax\r
+    .byte 0x2e\r
+    movw    %ax, -6(%rdi)\r
+    #\r
+    # Switch into ProtectedMode\r
+    #\r
+    movq    %cr0, %rbx\r
+    .byte 0x66\r
+    andl    $0x9ffafff3, %ebx\r
+    .byte 0x66\r
+    orl     $0x00000023, %ebx\r
+\r
+    movq    %rbx, %cr0\r
+    .byte 0x66, 0xea\r
+    .space 6\r
+\r
+_GdtDesc:    .space  6\r
+\r
+ProtectedMode:\r
+    movw    $PROTECT_MODE_DS, %ax\r
+    movl    %eax, %ds\r
+    movl    %eax, %es\r
+    movl    %eax, %fs\r
+    movl    %eax, %gs\r
+    movl    %eax, %ss\r
+    .byte   0xbc                       # mov esp, imm32\r
+ASM_PFX(gSmiStack):   .space  4\r
+    jmp     ProtFlatMode\r
+\r
+ProtFlatMode:\r
+    .byte   0xb8\r
+ASM_PFX(gSmiCr3):    .space  4\r
+    movq    %rax, %cr3\r
+    movl    $0x668,%eax                 # as cr4.PGE is not set here, refresh cr3\r
+    movq    %rax, %cr4                  # in PreModifyMtrrs() to flush TLB.\r
+# Load TSS\r
+    subl    $8, %esp                    # reserve room in stack\r
+    sgdt    (%rsp)\r
+    movl    2(%rsp), %eax               # eax = GDT base\r
+    addl    $8, %esp\r
+    movl    %eax, %edx\r
+    addl    $GDT_SIZE, %edx\r
+    movb    %dl, (TSS_SEGMENT + 2)(%rax)\r
+    movb    %dh, (TSS_SEGMENT + 3)(%rax)\r
+    .byte   0xc1, 0xea, 0x10             # shr     edx, 16\r
+    movb    %dl, (TSS_SEGMENT + 4)(%rax)\r
+    movb    %dh, (TSS_SEGMENT + 7)(%rax)\r
+    movl    %eax, %edx\r
+    movb    $0x89, %dl\r
+    movb    %dl, (TSS_SEGMENT + 5)(%rax) # clear busy flag\r
+    movl    $TSS_SEGMENT, %eax\r
+    ltr     %ax\r
+\r
+    #\r
+    # Switch to LongMode\r
+    #\r
+    pushq    $LONG_MODE_CS                # push cs hardcore here\r
+    call     Base                         # push return address for retf later\r
+Base:\r
+    addl    $(LongMode - Base), (%rsp)  # offset for far retf, seg is the 1st arg\r
+    movl    $0xc0000080, %ecx\r
+    rdmsr\r
+    orb     $1,%ah\r
+    wrmsr\r
+    movq    %cr0, %rbx\r
+    btsl    $31, %ebx\r
+    movq    %rbx, %cr0\r
+    retf\r
+LongMode:                               # long mode (64-bit code) starts here\r
+    movabsq $ASM_PFX(gSmiHandlerIdtr), %rax\r
+    lidt    (%rax)\r
+    lea     (DSC_OFFSET)(%rdi), %ebx\r
+    movw    DSC_DS(%rbx), %ax\r
+    movl    %eax,%ds\r
+    movw    DSC_OTHERSEG(%rbx), %ax\r
+    movl    %eax,%es\r
+    movl    %eax,%fs\r
+    movl    %eax,%gs\r
+    movw    DSC_SS(%rbx), %ax\r
+    movl    %eax,%ss\r
+#   jmp     _SmiHandler                 ; instruction is not needed\r
+\r
+_SmiHandler:\r
+    movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax\r
+    cmpb    $0, (%rax)\r
+    jz      L1\r
+\r
+    .byte   0x48, 0x8b, 0x0d            # mov rcx, [rip + disp32]\r
+    .long   SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)\r
+    .byte   0x48, 0x8b, 0x15            # mov rdx, [rip + disp32]\r
+    .long   SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)\r
+    movq    %rcx, %dr6\r
+    movq    %rdx, %dr7\r
+L1:\r
+\r
+    movabsq $ASM_PFX(SmiRendezvous), %rax\r
+    movq    (%rsp), %rcx\r
+    # Save FP registers\r
+\r
+    subq    $0x208, %rsp\r
+    .byte   0x48                        # FXSAVE64\r
+    fxsave  (%rsp)\r
+\r
+    addq    $-0x20, %rsp\r
+    call    *%rax\r
+    addq    $0x20, %rsp\r
+\r
+    #\r
+    # Restore FP registers\r
+    #\r
+    .byte   0x48                        # FXRSTOR64\r
+    fxrstor (%rsp)\r
+\r
+    movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax\r
+    cmpb    $0, (%rax)\r
+    jz      L2\r
+\r
+    movq    %dr7, %rdx\r
+    movq    %dr6, %rcx\r
+    .byte   0x48, 0x89, 0x15            # mov [rip + disp32], rdx\r
+    .long   SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)\r
+    .byte   0x48, 0x89, 0x0d            # mov [rip + disp32], rcx\r
+    .long   SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)\r
+L2:\r
+    rsm\r
+\r
+ASM_PFX(gcSmiHandlerSize):    .word      . - _SmiEntryPoint\r